[GESP202412 七级] 武器购买 题解
lby_commandBlock · · 题解
前言
看到这些题目,就要想到这道题要用什么算法来做,例如这道题要动态规划。
下文中的
思路
按照动态规划的步骤进行思考。动态规划五部曲。
- dp 数组以及下标的含义。
设
- 递推公式。
-
若
c_i > j ,即该武器的花费大于了总花费(下文称预算),则dp_{i,j} 就直接从dp_{i-1,j} 进行转移。 -
若
c_i \leq j ,即该武器的花费小于预算,就有买和不买两种情况。
- dp 数组如何初始化。
由于 dp 要求最大的强度和,所以直接将 dp 数组初始化为
- 遍历顺序。
由于求
- 打印 dp 数组。
按照 -1 即可。
代码
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int T, n, P, Q, p[109], c[109], dp[109][50009];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> T;
while (T--) {
cin >> n >> P >> Q;
for (int i = 1; i <= n; i++)
cin >> p[i] >> c[i];
// 初始状态
memset(dp, 0, sizeof(dp));
// DP
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= Q; j++) {
// 不买
dp[i][j] = dp[i - 1][j];
// 若可以买,就把买和不买取最大值
if (c[i] <= j)
dp[i][j] = max(dp[i][j], dp[i - 1][j - c[i]] + p[i]);
}
}
// 打印
bool flag = true;
for (int q = 1; q <= Q; q++) {
if (dp[n][q] >= P) {
cout << q << endl;
flag = false;
break;
}
}
if (flag)
cout << -1 << endl;
}
return 0;
}