基于一维的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.0分

4 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论