首先01揹包題目的雛形是ios
有N件物品和一個容量爲V的揹包。第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可以使價值總和最大。編程
01揹包的特色就是:每種物品僅有一件,能夠選擇放或不放。數組
其狀態轉移方程是:url
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
spa
對於這方方程其實並不難理解,方程之中,如今須要放置的是第i件物品,這件物品的體積是c[i],價值是w[i],所以f[i-1][v]表明的就是不將這件物品放入揹包,而f[i-1][v-c[i]]+w[i]則是表明將第i件放入揹包以後的總價值,比較二者的價值,得出最大的價值存入如今的揹包之中。code
理解了這個方程後,將方程代入實際題目的應用之中,可得blog
1 for(i = 1; i<=n; i++) 2 { 3 for(j = v; j>=c[i]; j--)//在這裏,揹包放入物品後,容量不斷的減小,直到再也放不進了 4 { 5 f[i][v]=max(f[i-1][v],f[i-1][j-c[i]]+w[i]); 6 } 7 }
也能夠經過一維數組複用,來就行空間壓縮:ip
1 for(int i=0;i<n;i++) 2 { 3 for(int j=m;j>=h[i];j--) 4 { 5 dp[j]=max(dp[j],dp[j-h[i]]+v[i]); 6 } 7 }
來一發牛客上的一個雙重揹包問題ci
輸入數據包括x+1行:
第一行包括三個整數x(2 ≤ x ≤ 20),n(0 ≤ n ≤ 500),m(0 ≤ m ≤ 500),以空格分隔
接下來的x行,每行一個01串item[i],表示第i個物品。每一個物品的長度length(1 ≤ length ≤ 50)
輸出一個整數,表示牛牛最多能創造多少種物品
3 3 1 1 00 100
2
1 #include "iostream" 2 #include "string" 3 #include "vector" 4 #include "algorithm" 5 6 using namespace std; 7 8 int dp[505][505]; 9 int LL0[505], LL1[505]; 10 int x, n, m; 11 12 int main() 13 { 14 while (cin >> x >> n >> m) 15 { 16 for (int i = 0; i < x; i++) 17 { 18 string str; 19 cin >> str; 20 int l = str.length(), L0 = 0, L1 = 0; 21 for (int i = 0; i < l; i++) 22 { 23 if (str[i] == '0') 24 L0++; 25 else 26 L1++; 27 } 28 LL0[i + 1] = L0; 29 LL1[i + 1] = L1; 30 } 31 for (int i = 1; i <= x; i++) 32 { 33 for (int j = n; j >= LL0[i]; j--)//在這裏,揹包放入物品後,容量不斷的減小,直到再也放不進了 34 { 35 for (int k = m; k >= LL1[i]; k--) 36 dp[j][k] = max(dp[j][k], dp[j - LL0[i]][k - LL1[i]] + 1); 37 } 38 } 39 cout << dp[n][m] << endl; 40 } 41 } 42 43 //3 3 1 44 //1 45 //00 46 //100 47 48 //5 5 5 49 //1 50 //10 51 //00 52 //0 53 //0