寒假集训做题分享(2)
[ABC015D] 高橋くんの苦悩
知识点:二维费用背包。
根据翻译可知,这道题其实基本上就是一道二维背包的板子题,这里简单介绍一下二维费用背包。
首先,对于背包问题,我们必然是要用 \(dp\) 解决的。
定义状态
dp[i][j][k]
表示用前 \(i\) 件物品装入所能承受的最大重量为 \(j\) ,容积为
\(k\) 的背包的最大价值。
对于所有的背包问题,我们都有选与不选两种情况。
如果不选第 \(i\) 件物品,那么,就有
dp[i][j][k]=dp[i-1][j][k]
如果选择第 \(i\) 件物品,那么,由于第 \(i\) 件物品的重量为 \(a[ i ]\) ,体积为 1,所以
dp[i][j][k]=dp[i-1][j-a[i]][k-1]+b[i]
两者取最大值,就有
dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-a[i]][k-1]+b[i])
但是,这里的三维数组实际上是可以省掉一维的,所以,最终的状态转移方程式为
dp[i][j]=max(dp[i][j],dp[i-a[k]][j-1]+b[i])
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 11000;
int a[N], b[N], dp[N][N];
int main() {
int i, j, n, W, k, l;
cin >> W >> n >> k;
for (i = 1; i <= n; i++) {
cin >> a[i] >> b[i];
}
for (i = 1; i <= n; i++) {
for (j = W; j >= a[i]; j--) {
for (l = k; l >= 1; l--) {
dp[j][l] = max(dp[j][l], dp[j - a[i]][l - 1] + b[i]);
}
}
}
cout << dp[W][k] << endl;
return 0;
}