今天写题的时候碰到了一道完全背包题,可是没有看出来,乱写了一通,浪费了一个晚上,顺便复习一下背包的知识
01背包
每种物品只能选择一次或者不选,求背包容量内的最大价值
先给出状态转移方程:
f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
解释一下:f[i][j]表示的是前i个物品中,背包容量为j时,得到的最大价值;如果在容量为j时选择不放第i个物品,那么f[i][j]=f[i-1][j],f[i-1][j]表示前一个物品在容量j时的状态值;如果在容量为j时选择放第i个物品,那么f[i][j]=f[i-1][j-w[i]]+v[i],f[i-1][j-w[i]]+v[i]表示前一个物品得到的状态加上第i个物品的价值;自然而然,f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
下面是二维数组的代码,自己敲了一遍,加深印象
1 #include<cstdio> 2 int main() 3 { 4 int n,m,v[105],w[105],f[105][105]; 5 scanf("%d %d",&m,&n); 6 for(int i=1;i<=n;i++) 7 scanf("%d %d",&v[i],&w[i]); 8 for(int i=1;i<=n;i++) 9 { 10 for(int j=1;j<=m;j++) 11 { 12 if(w[i]<=j) 13 f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]); 14 else 15 f[i][j]=f[i-1][j]; 16 } 17 } 18 printf("%d",f[n][m]); 19 return 0; 20 }
还有一种是一维数组的方法,更能节省空间
1 #include<cstdio> 2 int main() 3 { 4 int n,m,v[105],w[105],f[105]; 5 scanf("%d %d",&m,&n); 6 for(int i=1;i<=n;i++) 7 scanf("%d %d",&v[i],&w[i]); 8 for(int i=1;i<=n;i++) 9 { 10 for(int j=m;j>=1;j--) 11 { 12 if(w[i]<=j) 13 f[j]=max(f[j],f[j-w[i]]+v[i]); 14 } 15 } 16 printf("%d",f[m]); 17 return 0; 18 }
里面第二个循环为什么要倒着来,遍历到第i个物品时,f[j]应该与第i-1个物品的状态比较,如果顺着来的话,f[j]则与第i个物品的状态进行了比较,这样会出事的;
完全背包
每种物品可以选无数次,求背包容量内的最大价值
状态转移方程为:f[j]=max(f[j],f[j-w[i]]+v[i]);
贴上代码:
1 #include<cstdio> 2 int main() 3 { 4 int n,m,v[105],w[105],f[105]; 5 scanf("%d %d",&m,&n); 6 for(int i=1;i<=n;i++) 7 scanf("%d %d",&v[i],&w[i]); 8 for(int i=1;i<=n;i++) 9 { 10 for(int j=w[i];j<=m;j++) 11 { 12 f[j]=max(f[j],f[j-w[i]]+v[i]); 13 } 14 } 15 printf("%d",f[m]); 16 return 0; 17 }
多重背包
每种物品能取有限次,求背包容量内的最大值
多重背包问题化作01背包问题解决,如果价值为v的物品有x个,则化成x个价值为v的物品;
#include<cstdio> int main() { int n,m,v[105],w[105],f[105]; scanf("%d %d",&m,&n); for(int i=1; i<=n; i++) scanf("%d %d",&v[i],&w[i],&num[i]); int k=n+1; for(int i=1; i<=n; i++) { for(int j=1; j<num[i]; j++) { v[k]=v[i]; w[k]=w[i]; k++; } } for(int i=1; i<k; i++) { for(int j=m; j>=1; j--) { if(w[i]<=j) f[j]=max(f[j],f[j-w[i]]+v[i]); } } printf("%d",f[m]); return 0; }
再贴上今天折腾了一晚上的题:http://acm.sdibt.edu.cn/JudgeOnline/problem.php?id=2340
把数组改为全局变量竟然就A了,问了老谭,说这是,没有清零的原因,脑瓜子疼!