题目描述
原题链接:4. 多重背包问题 I
解题思路
(1)二维数组
递推公式: d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j − 0 ∗ v [ i ] ] , d p [ i − 1 ] [ j − v [ i ] ] + w [ i ] , d p [ i − 1 ] [ j − 2 ∗ v [ i ] ] + w [ i ] + . . . + d p [ i − 1 ] [ j − s [ i ] ∗ v [ i ] ] + s [ i ] ∗ w [ i ] ) dp[i][j] = max(dp[i - 1][j - 0 * v[i]], dp[i - 1][j - v[i]] + w[i], dp[i - 1][j - 2*v[i]] + w[i] + ... + dp[i - 1][j - s[i]*v[i]] + s[i]*w[i]) dp[i][j]=max(dp[i−1][j−0∗v[i]],dp[i−1][j−v[i]]+w[i],dp[i−1][j−2∗v[i]]+w[i]+...+dp[i−1][j−s[i]∗v[i]]+s[i]∗w[i])
遍历时候,在最内层设置一个for循环,寻找从一个都不选到选s[i]个第i个物品时,哪种情况取得最大价值。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
int n, m;
int dp[N][N];
int v[N], w[N], s[N];
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> v[i] >> w[i] >> s[i];
for(int i = 1; i <= n; i++) {
for(int j = 0; j <= m; j++) {
// 一个都不选一直到选s[i]个,选择一种最大价值情况
for(int k = 0; k <= s[i]; k++) {
// 注意这里的判定条件应该只为k * v[i] <= j时情况,而不能是让k * v[i] > j 时,取dp[i][j]=dp[i-1][j],因为就算k*v[i]此时大于j,但是并不能代表其他k值时也大于j导致i这个背包情况被忽略。
if(k * v[i] <= j){
dp[i][j] = max(dp[i][j], dp[i - 1][j - k * v[i]] + k * w[i]);
}
}
}
}
cout << dp[n][m] << endl;
return 0;
}
Python
n, m = map(int, input().split())
v, w, s = [], [], []
for i in range(n):
item = list(map(int, input().split()))
v.append(item[0])
w.append(item[1])
s.append(item[2])
dp = [[0] * (m + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(m + 1):
dp[i][j] = dp[i - 1][j]
for k in range(s[i - 1] + 1):
if k * v[i - 1] <= j:
dp[i][j] = max(dp[i][j], dp[i - 1][j - k * v[i - 1]] + k * w[i - 1])
print(dp[n][m])
(2)一维滚动数组
在01背包一维滚动数组的基础上,内层再多个for循环。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
int n, m;
int dp[N];
int v[N], w[N], s[N];
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> v[i] >> w[i] >> s[i];
dp[0] = 0;
for(int i = 1; i <= n; i++) {
for(int j = m; j >= 0; j--) {
// 一个都不选一直到选s[i]个,选择一种最大价值情况
for(int k = 0; k <= s[i] && j >= k * v[i] ; k++) {
dp[j] = max(dp[j], dp[j - k * v[i]] + k * w[i]);
}
}
}
cout << dp[m] << endl;
return 0;
}