標籤:
一、背包問題分類:
我覺得簡單的背包問題分為兩類:一是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;}
acm——背包問題