背包DP第12课:多重背包DP应用案例实践1

题目描述
设有 1 g 1\mathrm{g} 1g、 2 g 2\mathrm{g} 2g、 3 g 3\mathrm{g} 3g、 5 g 5\mathrm{g} 5g、 10 g 10\mathrm{g} 10g、 20 g 20\mathrm{g} 20g 的砝码各若干枚(其总重 \\le 1000),可以表示成多少种重量?
输入格式
输入方式: a 1 , a 2 , a 3 , a 4 , a 5 , a 6 a_1 , a_2 ,a_3 , a_4 , a_5 ,a_6 a1,a2,a3,a4,a5,a6
(表示 1 g 1\mathrm{g} 1g 砝码有 a 1 a_1 a1 个, 2 g 2\mathrm{g} 2g 砝码有 a 2 a_2 a2 个, ... \dots ..., 20 g 20\mathrm{g} 20g 砝码有 a 6 a_6 a6 个)
输出格式
输出方式:Total=N
( N N N 表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况)
输入输出样例 1
输入 1
1 1 0 0 0 0
输出 1
Total=3
【题目来源】
NOIP 1996 提高组第四题
思路分析
问题本质:
- 这是一个多重背包问题,需要找出用给定数量的不同重量砝码能组成多少种不同的总重量。
核心思想:
- 使用动态规划,
dp[i]表示重量i是否可以被称出。
算法步骤:
- 初始化
dp[0] = true(0重量总是可达) - 三重循环遍历:
- 外层:遍历砝码种类(6种)
- 中层:遍历每种砝码的数量
- 内层:从大到小遍历可能的重量,进行状态转移
- 最后统计所有可达的重量数量
关键点:
- 内层循环从大到小遍历是为了避免重复使用同一个砝码
代码实现
cpp
#include<bits/stdc++.h>
using namespace std;
int n, a[7]; // a数组存储每种砝码的数量
int w[7] = {0, 1, 2, 3, 5, 10, 20}; // 砝码重量数组,索引从1开始对应
bool dp[1010]; // dp数组,dp[i]表示能否称出重量i
int main() {
// 读取6种砝码的数量
for(int i = 1; i <= 6; i++) cin >> a[i];
// 初始化动态规划数组,重量0总是可以称出(不使用任何砝码)
dp[0] = true;
// 动态规划过程
for(int i = 1; i <= 6; i++) { // 遍历6种砝码
for(int k = 1; k <= a[i]; k++) { // 遍历当前砝码的每个实例
for(int j = 1000; j >= w[i]; j--) { // 从大到小遍历重量
// 如果j-w[i]重量可以称出,那么j重量也可以称出
if(dp[j - w[i]]) {
dp[j] = true;
}
}
}
}
// 统计能称出的不同重量个数(不包括0)
int ans = 0;
for(int i = 1; i <= 1000; i++) {
if(dp[i]) {
ans++;
}
}
cout << "Total=" << ans;
return 0;
}
复杂度分析
时间复杂度:O(6 × max(a[i]) × 1000),在给定约束下是可接受的。
空间复杂度:O(1000),使用一维数组优化空间。
完整系列资料,请查看专栏:《csp信奥赛C++动态规划》
https://blog.csdn.net/weixin_66461496/category_13096895.html
各种学习资料,助力大家一站式学习和提升!!!
cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
cout<<"########## 一站式掌握信奥赛知识! ##########";
cout<<"############# 冲刺信奥赛拿奖! #############";
cout<<"###### 课程购买后永久学习,不受限制! ######";
return 0;
}
- 一、CSP信奥赛C++通关学习视频课:
- C++语法基础
- C++语法进阶
- C++算法
- C++数据结构
- CSP信奥赛数学
- CSP信奥赛STL
- 二、CSP信奥赛C++竞赛拿奖视频课:
- 信奥赛csp-j初赛高频考点解析
- CSP信奥赛C++复赛集训课(12大高频考点专题集训)
- 三、考级、竞赛刷题题单及题解:
- GESP C++考级真题题解
- CSP信奥赛C++初赛及复赛高频考点真题解析
- CSP信奥赛C++一等奖通关刷题题单及题解
详细内容:
1、csp/信奥赛C++,完整信奥赛系列课程(永久学习):
https://edu.csdn.net/lecturer/7901 点击跳转



2、CSP信奥赛C++竞赛拿奖视频课:
https://edu.csdn.net/course/detail/40437 点击跳转

3、csp信奥赛冲刺一等奖有效刷题题解:
CSP信奥赛C++初赛及复赛高频考点真题解析(持续更新):https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转
- 2025 csp-j 复赛真题及答案解析(最新更新)
- 2025 csp-x(山东) 复赛真题及答案解析(最新更新)
- 2025 csp-x(河南) 复赛真题及答案解析(最新更新)
- 2025 csp-x(辽宁) 复赛真题及答案解析(最新更新)
- 2025 csp-x(江西) 复赛真题及答案解析(最新更新)
- 2025 csp-x(广西) 复赛真题及答案解析(最新更新)
- 2020 ~ 2024 csp 复赛真题题单及题解
- 2019 ~ 2022 csp-j 初赛高频考点真题分类解析
- 2021 ~ 2024 csp-s 初赛高频考点解析
- 2023 ~ 2024 csp-x (山东)初赛真题及答案解析
- 2024 csp-j 初赛真题及答案解析
- 2025 csp-j 初赛真题及答案解析(最新更新)
- 2025 csp-s 初赛真题及答案解析(最新更新)
- 2025 csp-x (山东)初赛真题及答案解析(最新更新)
- 2025 csp-x (江西)初赛真题及答案解析(最新更新)
- 2025 csp-x (辽宁)初赛真题及答案解析(最新更新)
CSP信奥赛C++一等奖通关刷题题单及题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12673810.html 点击跳转
- 129 道刷题练习和详细题解,涉及:模拟算法、数学思维、二分算法、 前缀和、差分、深搜、广搜、DP专题、 树和图
4、GESP C++考级真题题解:

GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转
· 文末祝福 ·
cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
cout<<"跟着王老师一起学习信奥赛C++";
cout<<" 成就更好的自己! ";
cout<<" csp信奥赛一等奖属于你! ";
return 0;
}