問題:
有N件物品和一個容量為V的背包。第i件物品的價值是c[i],重量是w[i]。求解將哪些物品裝入背包可使這些物品的重量總和不超過背包容量,且價值總和最大。
這個問題的特點是:每種物品只有一件,可以選擇放或者不放。用f[i][j]表示背包當前容量為j,選擇裝入1-i個物品時的最大價值
在求最優解的背包問題中,一般有兩種不同的問法:1、求小於等於背包容量的最優解,即不一定恰好裝滿背包;2、要求“恰好裝滿背包”時的最優解.
1、求小於等於背包容量的最優解,即不一定恰好裝滿背包;
設f[0..N][0..v]=0
2、要求“恰好裝滿背包”時的最優解.
則f[0][1..v]=-∞,確保當背包不滿時得不到最優解(價值最大)
狀態轉移方程:
解釋:
1.背包當前容量j小於第i件物品的重量w[i-1],第i件物品裝不下,所有不放第i件物品
2.第i件物品可以放下,進行選擇,放或者不放
在“其它”情況下,f[i][j]的值就是上述兩種情況中的最大值
代碼:
1 #include<iostream> 2 using namespace std; 3 int f[100][100]; 4 int Min=-999999; 5 int package(int n,int v,int w[],int c[]) //n-物品數量,v-背包容量,w[]各個物品的重量,c[]對應物品的價值 6 { 7 if(f[n][v]!=0) //已計算過該子問題 8 return f[n][v]; 9 if(n==0||v<=0) //題型一:價值最大,不要求裝滿 10 return 0; 11 12 //if(n==0) //題型二:背包裝滿的情況下最大價值,設f[0][0]=0,f[0][1..v]=-∞,即當背包不滿時沒有最優解 13 //{ 14 // if(v!=0) return Min; 15 // return 0; 16 //} 17 18 if(v<w[n-1]) //第n件物品的重量大於當前背包的容量,則不裝第n件物品,背包容量仍為v,從剩余的n-1件物品中選擇 19 f[n][v]=package(n-1,v,w,c); 20 else //背包當前容量可以裝下第n件物品,可以選擇裝或者不裝第n件物品 21 { 22 int a=package(n-1,v,w,c); //不裝第n件物品,從剩余的n-1件物品中選擇,背包容量仍為v 23 int b=package(n-1,v-w[n-1],w,c)+c[n-1]; //裝第n件物品,則當前價值為第n件物品的價值c[n]加上(n-1,v-w[n])問題的最優解 24 f[n][v]=a>b?a:b; //選擇價值最大的解 25 } 26 return f[n][v]; 27 } 28 29 int main() 30 { 31 memset(f,0,sizeof(f)); //設置邊界條件 32 int n,v,w[100],c[100]; 33 cout<<"input the number of items:"; 34 cin>>n; 35 cout<<"input the volume of items:"; 36 cin>>v; 37 cout<<"input the weight of items:"; 38 for(int i=0;i<n;i++) 39 cin>>w[i]; 40 cout<<"input the value of items:"; 41 for(int i=0;i<n;i++) 42 cin>>c[i]; 43 cout<<"the bigest value is:"; 44 cout<<package(n,v,w,c)<<endl; 45 } View Code結果:
問法一:求小於等於背包容量的最優解,即不一定恰好裝滿背包;
問法二:要求“恰好裝滿背包”時的最優解.