基于一维的01背包
首先想想为什么01背包中要按照v=V..0的逆序来循环。这是因为要保证第i次循环中的状态fi是由状态f[i-1] [v-c[i]]递推而来。换句话说,这正是为了保证每件物品只选一次,保证在考虑“选入第i件物品”这件策略时,依据的是一个*绝无已经选入第i件物品的 子结果 *f[i-1] [v-c[i]]。而现在完全背包的特点恰是每种物品可选无限件,所以在考虑“加选一件第i种物品”这种策略时,却正需要一个可能已选入第i种物品的子结果fi],所以就可以并且必须采用v=0..V的顺序循环。这就是这个简单的程序为何成立的道理。
01背包于完全背包的区别就在于:01背包的dp[i] [j] 需要dp[i - 1] [j - v[i]]这个子结果,即在选第i - 1个物品时且剩余的容量恰好够v[i]的子结果,因为在选第i - 1 个时绝对不可能选了第i 个,这样就保证的一件物品只能选一次;
而完全背包第 I 件物品可选无限件,所以在考虑“加选一件第 i 种物品“时,需要考虑是:可能已经选入第 i 种物品的子结果dp[i] [j - v[i]]
参考代码:
#include<iostream> using namespace std; const int M = 10000; int m, n; int dp[M], w[M], c[M]; int main(){ cin>>m>>n; for(int i = 0; i < n; i++){ cin>>w[i]>>c[i]; } for(int i = 0; i < n; i++){ for(int j = 0; j <= m; j++){ if(j >= w[i]){ dp[j] = max(dp[j], dp[j - w[i]] + c[i]); } } } cout<<"max="<<dp[m]; return 0; }
0.0分
4 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复