寵物小精靈之收服
題解:設狀態 \(dp[i][j][k]\) 表示從前 \(i\) 個物品中選擇,物品的費用 \(1\) 為 \(j\),費用 \(2\) 為 \(k\) 的最大選擇數量。
則狀態轉移方程為:
\[dp[i][j][k] = max(dp[i - 1][j][k], dp[i - 1][j - v_1[i]][k - v_2[i]] + 1)
\]
跟普通01揹包一樣,第一維可以直接最佳化掉。
第一問的答案顯然為 \(dp[n][m - 1]\) (注意本題中體力不能為0),第二問的答案列舉滿足 \(dp[n][i] = dp[n][m - 1]\) 的最大的 \(m - i\) 即為答案。
AC程式碼:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010;
int dp[N][N];
int v[N], w[N];
void solve() {
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= k; i ++) {
cin >> v[i] >> w[i];
}
for (int i = 1; i <= k; i ++) {
for (int j = n; j >= v[i]; j --) {
for (int t = m - 1; t >= w[i]; t --) {
dp[j][t] = max(dp[j][t], dp[j - v[i]][t - w[i]] + 1);
}
}
}
int res = 1e9;
for (int i = 0; i < m; i ++) {
if(dp[n][i] == dp[n][m - 1]) {
res = min(res, i);
break;
}
}
cout << dp[n][m - 1] << " " << m - res << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
}