完全背包问题,没啥好说的,直接套板子,但是有一点我没注意到,wa了好久,简直被自己蠢哭了
状态转移方程中,关于物品挑选的件数,循环的上限是物品的总数量和当前的钱能买的数量的最小值
而且完全背包的转移方程是这样的
for (int i = 1; i <= m; i++){
for (int j = 0; j <= n; j++){
for (int k = 0; k <= j / p[i] && k <= c[i]; k++){
dp[i][j] = max(dp[i][j], dp[i - 1][j - k * p[i]] + k * h[i]);
}
}
}
01背包和完全背包的状态不同
01背包的状态是放与不放
而完全背包是放入0个,1个、、、(多个)
因为每次都要更新自身,所以方程中会出现
dp[i][j] = max(dp[i][j], dp[i - 1][j - k * p[i]] + k * h[i]);
也就是说,这个方程是可以通过01背包推过来的,如果我们给dp[ i ] [ j ]赋值为dp[ i - 1] [ j ](相当于不选或者是选 0 个),我们就可以跳过k = 0的循环
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
int n, t, m;
const int maxn = 110;
int h[maxn], c[maxn], p[maxn];
int dp[maxn][maxn];
int main()
{
scanf("%d", &t);
while (t--){
memset(dp, 0, sizeof dp);
scanf("%d %d", &n ,&m);
for (int i = 1; i <= m; i++){
scanf("%d %d %d", p + i, h + i, c + i);
}
for (int i = 1; i <= m; i++){
for (int j = 0; j <= n; j++){
dp[i][j] = dp[i - 1][j];
for (int k = 1; k <= j / p[i] && k <= c[i]; k++){
dp[i][j] = max(dp[i][j], dp[i - 1][j - k * p[i]] + k * h[i]);
}
}
}
printf("%d\n", dp[m][n]);
}
return 0;
}