标签:
一、背包问题分类:
我觉得简单的背包问题分为两类:一是01背包问题:每个物品只有拿或者不拿两种选项;另一种就是非01背包问题,每种物品的重量只要不超过背包的最大容量,可以拿任意多个。
背包问题还可以按照求最大或者最小分类;
还可以根据是否一定要充满背包分成充满和不充满;
二、背包问题的一般递推:
我只知道一种方法:假设我们要求价值最大的值;背包的容量为w;每件物品i的价值为val[i],重量为vol[i];我们先定义f[j]为背包容量为j时,所容物品的价值最大值;所以我们得到f[j]的递推公式:
f[j]=max(f[j],f[j-vol[i]]+val[i]);
当然我们不能马上使用,要根据具体的情况选择不同的方式表达。
1.首先是一般背包最大值问题,每种物品的重量只要不超过背包的最大容量,可以拿任意多个,同时需要充满背包;
设有n件物品,背包的容量为w,每件物品i的价值为val[i],重量为vol[i],f[j]为背包容量为j时,所容物品的价值最大值;我们可以这么写:
for(i=1;i<=n;i++) { for(j=vol[i];j<=w;j++) { f[j]=max(f[j-vol[i]]+val[i],f[j]); } }
2.01背包最大值问题,每个物品只有拿或者不拿两种选项,同时需要充满背包;
设有n件物品,背包的容量为w,每件物品i的价值为val[i],重量为vol[i],f[j]为背包容量为j时,所容物品的价值最大值;我们可以这么写:
for(i=1;i<=n;i++) { for(j=w;j>=vol[i];j--) { f[j]=max(f[j-vol[i]]+val[i],f[j]); } }
这里注意,因为是01背包问题,每件物品只能拿一件,所以j从w开始递减,这样保证了每件物品只拿一件。
同时注意,上面所说的开始时要初始化memset(f,0,sizeof(f));如果背包不能充满,则f[w]=0;
3.一般背包最大值问题,每种物品的重量只要不超过背包的最大容量,可以拿任意多个,同时不需要充满背包;这里只要一点点改动即可:
for(i=1;i<=n;i++) { for(j=vol[i];j<=w;j++) { m=max(f[j-vol[i]]+val[i],f[j]); if(f[j]<m) f[j]=m; } }
4.同理,01背包最大值问题,不需要充满背包时:
for(i=1;i<=n;i++) { for(j=w;j>=vol[i];j--) { m=max(f[j-vol[i]]+val[i],f[j]); if(m>f[j]) f[j]=m; } }
求最小时,只要将上面的max换成min即可。
这里,以hdu的两道题为:
hdu2602
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int main() { int t,n,w,f[1001],vol[1001],val[1001] ,m,i,j; scanf("%d",&t); while(t--) { m=0; memset(f,0,sizeof(f)); scanf("%d %d",&n,&w); for(i = 1 ; i <= n ; i++) scanf("%d",&val[i]); for(i = 1 ; i <= n ; i++) scanf("%d",&vol[i]); for(i = 1 ; i <= n ; i++) { for(j = w ; j >= vol[i] ; j--) { m=f[j-vol[i]]+val[i]; if(f[j]<m) f[j]=m; } } printf("%d\n",f[w]); } return 0; }
hdu1114
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define min(a,b) ((a)<(b)?(a):(b)) int main() { int t,n,w,f[10010],vol[1001],val[1001] ,m,i,j,a,b; scanf("%d",&t); while(t--) { m=0; scanf("%d %d",&a,&b); w=b-a; for(i=0;i<=w;i++) f[i]=500000000; scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d%d",&val[i],&vol[i]); f[0]=0; for(i=1;i<=n;i++) { for(j=vol[i];j<=w;j++) { f[j]=min(f[j-vol[i]]+val[i],f[j]); } } if(f[w]==500000000) printf("This is impossible.\n"); else printf("The minimum amount of money in the piggy-bank is %d.\n",f[w]); } return 0; }
标签:
原文地址:http://www.cnblogs.com/vallzey/p/4868573.html