以下是 ChatGPT 的分析,显然他数组开大了,但是开小之后仍然过不了样例:
正在为您搜索:洛谷中的题目、P5662、CSP-J2019、纪念品
以下是使用动态规划算法解决洛谷 P5662 [CSP-J2019] 纪念品问题的核心代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 10010;
int dp[N][N];
int main() {
int t, n, m;
cin >> t >> n >> m;
int price[N][N];
for (int i = 1; i <= t; i++) {
for (int j = 1; j <= n; j++) {
cin >> price[i][j];
}
}
// 初始化状态
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= m; i++) { // 初始金币数量
dp[1][i] = i;
}
// 状态转移
for (int i = 2; i <= t; i++) { // 第 i 天
for (int j = 1; j <= m; j++) { // 手头金币数量
dp[i][j] = dp[i-1][j]; // 不进行交易,保持上一天的状态
for (int k = 1; k <= n; k++) { // 针对每种纪念品的价格进行枚举
if (j >= price[i][k]) { // 如果手头金币够购买该种纪念品
dp[i][j] = max(dp[i][j], dp[i][j-price[i][k]] + price[i][1] - price[i][k]); // 进行交易,更新状态
}
}
}
}
// 超能力消失的最后一天,小伟需要将所有的纪念品出售换取金币
int res = dp[t][m];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
res = max(res, dp[t][j] + (m-j)*price[t][i]);
}
}
cout << res << endl;
return 0;
}
在以上代码中,我们使用了一个二维数组 dp 来表示状态。其中,dp[i][j] 表示在第 i 天结束时,手头有 j 枚金币所能获得的最大金币数量。
在进行状态转移时,首先考虑不进行交易的情况,即 dp[i][j]=dp[i−1][j],保持上一天的状态不变。接着,对于每种纪念品的价格,如果当前手头的金币数足以购买,则尝试进行交易。在交易的过程中,需要考虑可以购买的最大数量,以及购买和出售所需要支付的手续费。具体来说,如果当天购买某种纪念品,则收益为该种纪念品当天的出售价格减去购买价格和手续费。因此,可以得到状态转移方程:
dp[i][j]=max{dp[i−1][j],dp[i][j−price[i][k]]+price[i][1]−price[i][k]}
其中,price[i][k] 表示第 i 天第 k 种纪念品的价格,price[i][1] 表示第 i 天第 1 种纪念品的出售价格。
最后需要注意,在超能力消失的最后一天,小伟需要将所有的纪念品出售换取金币,以最大化其手头上的金币数量。因此,需要遍历每种纪念品的价格,并计算出交易后获得的收益,并取最大值即可。
参考资料:[1]