最經典的揹包問題莫過於是0/1揹包和完全揹包了。
1.0/1揹包
題目描述
一個旅行者有一個最多能用 m 公斤的揹包,現在有 n 件物品,它們的重量分別是 W1 ,W2 ,… , Wn ,它們的價值分別爲 C1,C2 ,… ,Cn 。若每種物品只有一件求旅行者能獲得最大總價值。
輸入格式
第 1 行:兩個整數,M(揹包容量,M≤200)和 N(物品數量,N≤30)。
第 2..N+1 行:每行二個整數 Wi,Ci,表示每個物品的重量和價值。
輸出格式
僅一行,一個數,表示最大總價值。
樣例數據
輸入
10 4
2 1
3 3
4 5
7 9
輸出
12
0/1揹包的特點就是每種物品只有一件,獨一無二,你只能選擇是裝這種物品,還是不裝這種物品。
用一個f[i][j]數組,表示前i件物品,總重量不超過j的最大價值。
若當前物品放入揹包,則 f[i][j]= f[i-1][j-w[i]]+c[i] ,即前i-1件物品的總價值加當前物品。
若物品不放入揹包,則前後總重量與總價值不變,僅i+1。
此時f[i][j]=f[i-1][j]
總方程 f[i][j]=max( f[i-1][j-w[i]]+c[i],f[i-1][j])
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
int m,n;
int w[33],c[33],f[33][203];
int main()
{
cin>>m>>n;
for(int i=1;i<=n;i++)
cin>>w[i]>>c[i];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(j>=w[i])
f[i][j]=max(f[i-1][j-w[i]]+c[i],f[i-1][j]);
else
f[i][j]=f[i-1][j];
cout<<f[n][m]<<endl;
return 0;
}
2.完全揹包
題目描述
設有 n 種物品,每種物品有一個重量及一個價值。但每種物品的數量是無限的,同時有一個揹包,最大載重量爲 M ,今從 n 種物品中選取若干件(同一種物品可以多次選取),使其重量的和小於等於 M ,而價值的和爲最大。
輸入格式
第 1 行:兩個整數,M(揹包容量,M<=200)和 N(物品數量,N<=200)。
第 2..N+1 行:每行二個整數 Wi,Ci,表示每個物品的重量和價值。
輸出格式
僅一行,一個數,表示最大總價值。
樣例數據
輸入
12 4
2 1
3 3
4 5
7 9
輸出
15
完全揹包與0/1揹包的區別在於每種物品的個數是無限的,也就是說你可以拿任意多件的某種物品,而不是獨一無二。
因此狀態轉移方程也會有些許變化。
依舊用0/1揹包的思路。
用一個f[i][j]數組,表示前i件物品,總重量不超過j的最大價值。
若物品不放入揹包,則前後總重量與總價值不變,僅i+1,這與0/1揹包完全一樣
此時f[i][j]=f[i-1][j]
若物品放入揹包,由於每種物品可以取多件
f[i][j]=f[i][j-w[i]]+c[i]
總方程 f[i][j]=max(f[i][j-w[i]]+c[i],f[i-1][j])
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
int m,n;
int w[210],c[210],f[210][210];
int main()
{
cin>>m>>n;
for(int i=1;i<=n;i++)
cin>>w[i]>>c[i];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(j>=w[i])
f[i][j]=max(f[i][j-w[i]]+c[i],f[i-1][j]);
else
f[i][j]=f[i-1][j];
cout<<f[n][m]<<endl;
return 0;
}
其實二者代碼差不多,只是狀態轉移方程有些許不同。
——我認爲return 0,是一個時代的終結。