求助样例过不去
查看原帖
求助样例过不去
527243
Iamzzr楼主2023/4/6 12:21

以下是 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]dp[i][j] 表示在第 ii 天结束时,手头有 jj 枚金币所能获得的最大金币数量。

在进行状态转移时,首先考虑不进行交易的情况,即 dp[i][j]=dp[i−1][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]}dp[i][j] = \max\{dp[i-1][j], dp[i][j-price[i][k]]+price[i][1]-price[i][k]\}

其中,price[i][k]price[i][k] 表示第 ii 天第 kk 种纪念品的价格,price[i][1]price[i][1] 表示第 ii 天第 11 种纪念品的出售价格。

最后需要注意,在超能力消失的最后一天,小伟需要将所有的纪念品出售换取金币,以最大化其手头上的金币数量。因此,需要遍历每种纪念品的价格,并计算出交易后获得的收益,并取最大值即可。

参考资料:[1]

2023/4/6 12:21
加载中...