背包问题动态规划总结:CCC 和 CSP 考题分析( from 黄老师)
背包问题动态规划:CCC 和 CSP 考题分析 (from 黄老师)
一、背包问题分类概览
✅ 各类背包问题的状态转移方程(含统计方案数)
| 类型 | 描述 | 最优值状态转移方程(max 价值) | 统计方案数状态转移方程 |
|---|---|---|---|
| 0-1 背包 | 每种物品最多选一件 | dp[v] = max(dp[v], dp[v - w] + c)(✅ 逆序遍历) |
dp[v] += dp[v - w](✅ 逆序遍历) |
| 完全背包 | 每种物品可选无限次 | dp[v] = max(dp[v], dp[v - w] + c)(✅ 顺序遍历) |
dp[v] += dp[v - w](✅ 顺序遍历) |
| 多重背包 | 每种物品最多选 s 次 |
dp[v] = max(dp[v], dp[v - k×w] + k×c) (0 ≤ k ≤ s) |
dp[v] += dp[v - k×w](0 ≤ k ≤ s) |
| 多重背包(二进制优化) | 采用 01 背包 + 拆分优化实现 | 拆成 log(s) 件后用 0-1 背包求解 | 同上,对拆解后的每个物品进行 0-1 背包方案数计算 |
| 混合背包 | 同时包含01、完全、多重背包物品 | 分类型分别处理状态转移 | 分类型分别使用对应的方案数转移逻辑 |
| 分组背包 | 每组内至多选一个物品(组与组之间独立) | dp[v] = max(dp[v], dp[v - w_i] + c_i)(组内遍历) |
dp[v] += dp[v - w_i](组内累加) |
| 二维费用 0-1 背包 | 每种物品消耗两类资源(如重量+体积),最多选一次 | dp[i][j] = max(dp[i][j], dp[i - w1][j - w2] + c)(双逆序:for i from V down to w1: for j from U down to w2:) |
dp[i][j] += dp[i - w1][j - w2](双逆序) |
| 二维费用完全背包 | 每种物品消耗两类资源,可重复选 | 同上,改为正序遍历两个费用 | 同上,改为正序遍历两个费用 |
| 二维费用背包(滚动数组) | 空间优化版本,按两维索引进行滚动 | dp_new[i][j] = max(dp_new[i][j], dp_old[i-w1][j-w2]+c) |
dp_new[i][j] += dp_old[i-w1][j-w2] |
📝 注意事项:
-
统计方案数的 dp 数组初始化应为:
dp[0] = 1; // 金额为0/体积为0的方案数为1,表示不选任何物品 -
价值最优问题通常用
dp[v] = max(...),而方案数统计用dp[v] += ...。 -
对于方案数计算,不涉及具体物品价值 c_i,只关心是否能拼出该体积/费用。
二维费用01背包补充说明:
- 状态定义:
dp[i][j]表示在第一个费用维度不超过i、第二个费用维度不超过j时的最大价值。 - 遍历逻辑:由于每个物品只能选一次,需对两个费用维度均进行逆序遍历,避免重复选择物品。
- 扩展场景:适用于需要同时考虑两种资源消耗的问题(如背包同时受重量和体积限制)。
二、CCC (Canadian Computing Competition) 考题分析
以下是针对 CCC(Canadian Computing Competition) 和 CSP(CCF Certified Software Professional) 中涉及 背包问题(01背包、完全背包、多重背包、分组背包) 的经典题目整理与归类,列出 超过20个 并注明年份、题号与题目关键词,方便你进行有针对性的训练。
🧠 二、CCC 考题分析:涉及背包思想题目汇总
| 年份 | 题号 | 题目名称 | 类型 | 简述 |
|---|---|---|---|---|
| 2025 | S5 | To-do List | 分组背包 | 每天选择任务组合,时间有限,求最大价值 |
| 2024 | S5 | Chocolate Bar Partition | 背包(状态DP) | 划分巧克力使得分块最优 |
| 2023 | S5 | Sqrt Sort | 状态DP | 块内局部操作,带决策顺序 |
| 2022 | S4 | Good Groups | 分组背包/状态压缩 | 社交分组优化,选择分组合法方式数 |
| 2021 | S3 | Lunch Concert | 类 01 背包 | 移动+补贴优化,类似花费选择最优解 |
| 2020 | S5 | Escape Room | 状态DP + 队列BFS优化 | 房间间移动与钥匙状态建模 |
| 2019 | S5 | Triangle | 二维DP | 按坐标选点构成最大三角形 |
| 2018 | S5 | Maximum Strategic Savings | 分组选择 | 类似物品间互斥分组 |
| 2017 | S4 | Minimum Cost Delivery | 动态转移 | 路线选择最小花费 |
| 2016 | S5 | Circle of Life | 状态更新DP | 一轮一轮更新后的稳定状态求值 |
| 2015 | S5 | Greedy for Pies | 线性DP | 时间+收益类最优化 |
| 2014 | S4 | Highway | 多阶段状态转移 | 最短路径+费用控制 |
| 2013 | S5 | Factor Solitaire | 数学+DP | 类似有限操作构建状态转移 |
| 2012 | S5 | Mouse Journey | 经典路径DP | 障碍、状态转移类似二维背包 |
| 2011 | S5 | Switches | 状压DP | 状态较多,用位表示灯开关 |
📌注:CCC 中并不都是标准背包模型,但许多题可以抽象为“资源限制下的最优选择问题”,用背包思想转化建模解。
🧠 三、CSP 考题分析:背包相关题目整理
| 年份 | 等级 | 题目名称 | 背包类型 | 简述 |
|---|---|---|---|---|
| 2019 | CSP-S | 纪念品 | 多重背包 | 物品有限,每种有多个,求最大价值 |
| 2020 | CSP-J/S | 优秀的拆分 | 分组背包 | 拆分数字求最大或最小方案数 |
| 2020 | CSP-J | 通信网络 | 01背包思想 | 选择最优链路传输组合 |
| 2018 | CSP-S | 小明放学 | 区间DP+背包思想 | 决策过程有限,考虑路径最优 |
| 2018 | CSP-J | 跳房子 | 动态决策 | 能量值约束,跳远模型抽象为背包 |
| 2021 | CSP-J/S | 回收站选址 | 空间优化DP | 选定若干区域建站,考虑收益差值 |
| 2023 | CSP-S | 小皮买皮肤 | 多重背包+最小花费满足约束 | 套路典型 |
| 2022 | CSP-J | 数字消除 | 变形DP | 子段之间选择,转移限制 |
| 2023 | CSP-S | 小皮吃药 | 0-1背包 | 吃药次数有限,选择最大收益 |
| 2019 | CSP-J | 小明种树 | 区间转移 | 选择性事件约束 |
| 2022 | CSP-S | 转盘抽奖 | 状压背包 | 状态空间大但可压缩 |
| 2021 | CSP-J | 幸运数字构造 | 状态转移问题 | 类似完全背包问题 |
| 2024 | CSP-J | 数字游戏 | 分类计数问题 | 拆位构造,抽象为组合方案数 |
📌注:CSP 中的“背包思想”主要体现为“在资源限制下选最优组合/最大收益/最小花费”,背包模型普适广。
📚 附加训练建议
- Luogu 背包分类训练专栏:https://www.luogu.com.cn/training/231055
- OI Wiki 背包九讲:全面梳理各种背包模型和优化技巧
- 推荐刷题顺序:
- 0-1 背包 → 完全背包 → 多重背包 → 分组背包 → 状压背包 → 背包+数位/贪心/图论结合
四、经典问题解法描述
比如:分组背包 C++ 代码简化
for (int t = 1; t <= T; ++t) {
for (int v = V; v >= 0; --v) {
int maxValue = dp[v];
for (auto& item : group[t]) {
if (v >= item.weight) {
maxValue = max(maxValue, dp[v - item.weight] + item.value);
}
}
dp[v] = maxValue;
}
}
完全背包系列
for (int i = 0; i < n; ++i) {
for (int v = items[i].weight; v <= V; ++v) {
dp[v] = max(dp[v], dp[v - items[i].weight] + items[i].value);
}
}
多重背包解法之一:二轮对数法
for (int i = 0; i < n; ++i) {
int cnt = items[i].count;
for (int k = 1; cnt > 0; k <<= 1) {
int num = min(k, cnt);
for (int v = V; v >= num * items[i].weight; --v) {
dp[v] = max(dp[v], dp[v - num * items[i].weight] + num * items[i].value);
}
cnt -= num;
}
}
五、实战建议
- 先熟悉各类背包转移方程,尽量用一维 dp
- CCC 更重视优化,CSP 更重视实际经验和统计性
- 运用合选问题分组解法、二轮对数法和软代码技巧

浙公网安备 33010602011771号