dp_01背包与完全背包

问题

完全背包

有n个物品
已经第i个物品重量wi 价值vi 无数个
总背包容量 W

01背包

有n个物品
已经第i个物品重量wi 价值vi 只有1个
总背包容量 W


思路:

设dp[i][j] i为考虑前i个物品时 j为背包总量。
则有
无后效性:i为前i个物品考虑, j为总量,两者均从小到大增加,i只需要跟i-1有关系。j并不是与j-1有关系,而是j与j+v[i] 有关系。
子问题重叠:使用dp[i-1][<j] 总满足
最优子结构:

  1. 01背包: dp[i][j+w[i]] = max(dp[i-1][j+w[i]],dp[i-1][j]+v[i]);//在选不选择i 中取最大值
  2. full背包: dp[i][j+w[i]] = max(dp[i-1][j+w[i]],dp[i][j]+v[i]);//在选择 0~n个i 中取最大值

但如果直接用二维,有些题会卡MLE 所以必须要用滚动数组更新


在最优子结构那里,对比01与full,不同点在于,dp[i-1][j]+v[i] 与 dp[i][j]+v[i]
这句在逻辑上的不同是:01只能选与不选 full则你可以选多少次都可以。
dp[i-1][j]+v[i] 为: 考虑前i-1个物品时 肯定加上i物品时
dp[i][j]+v[i] 为: 考虑前i个物品时 肯定加上i物品时(就算是已经考虑了i,也再加一次v[i])
滚动数组后,把i干掉。i的后效性不影响。
https://www.cnblogs.com/kingbuffalo/p/16228249.html 类似,因为只有一维数组,所以是需要考虑其遍历顺序的。

j要注意是:
01的dp下标影响是:dp[j+w[i]] 只能让 dp[j]+v[i] 的值影响一次。
按照从小到大的顺序,若令j=w[i] 则 dp[2*w[i]] 会进行有一次 将 v[i] * 2 的一次max对比。
故需要从大到小的顺序

而full的dp下标影响是:dp[j+w[i]] 只能让 dp[j]+v[i] 的值影响多次。
这时,就必须从小到大的顺序了。


练习题 AC代码

01背包 附 poj 3624 ac代码

#define MMAX 13000

int dp[MMAX];

int main(){
	int N,W;
	int wi,di;
	scanf("%d%d",&N,&W);
	for( int i=0;i<N;++i){
		scanf("%d%d",&wi,&di);
		for( int w=W;w>=wi;w--){
			dp[w] = max(dp[w],dp[w-wi]+di);
		}
	}
	printf("%d\n",dp[W]);
	return 0;
}

完全背包 附 poj1384 ac代码

#define INF 0x3f3f3f3f
#define NMAX 10005
int dp[NMAX];

int main(){
	int T;
	int E,F;
	int W;
	int N;
	int pi,wi;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&E,&F);
		W = F-E;
		memset(dp,0x3f,sizeof(dp));
		dp[0] = 0;
		scanf("%d",&N);
		for(int i=0;i<N;++i){
			scanf("%d%d",&pi,&wi);
			for( int j=wi;j<=W;++j){
				dp[j] = min(dp[j],dp[j-wi]+pi);
			}
		}
		if ( dp[W] == INF ){
			printf("This is impossible.\n");
		}else{
			printf("The minimum amount of money in the piggy-bank is %d.\n",dp[W]);
		}
	}
	return 0;
}

变种题

  1. 01背包求方案数 https://www.acwing.com/problem/content/description/280/
    解法:将 dp[w] += dp[w-wi]; dp[0]=1 倒序即可。其中dp[0]=1是指:0时也是方案的一种。
  2. 完全背包求方案数 https://www.acwing.com/problem/content/281/
    解法:将 dp[w] += dp[w-wi]; dp[0]=1 顺序即可。其中dp[0]=1是指:0时也是方案的一种。
posted @ 2022-05-11 15:51  传说中的水牛  阅读(32)  评论(0编辑  收藏  举报