模考T4卡牌游戏 题解


解题思路

这个问题需要动态规划来解决,关键在于处理费用翻倍的特殊机制。

  • 将卡牌按费用从大到小排序
  • 使用动态规划,状态转移时考虑费用减半(等价于费用翻倍的反向操作)
  1. 排序策略:将卡牌按费用从大到小排序,这样确保先处理费用高的卡牌,减少后续费用翻倍的影响
  2. 动态规划状态转移:状态转移方程:f[(j-c)/2] = max(f[(j-c)/2], f[j]+d)
    解释:使用当前卡牌后,剩余能量从 j 变为 j - c ,然后因为费用翻倍,相当于能量"贬值"为(j - c) \div 2
  3. 能量"贬值"处理:使用整数除法(j-c)/2来模拟费用翻倍的效果

复杂度分析

  • 时间复杂度:O(N \times M)
  • 空间复杂度:O(M)

接下来献上我写了两年半的代码

#include <bits/stdc++.h>
#define I using
#define AK namespace
#define IOI std
#define i_ak return
#define ioi 0
#define i_will signed
#define ak main
#define IMO ()
#define int long long
#define double long double //不要问我为什么这么像WYC的,问就是我抄他的
I AK IOI;
i_will ak IMO {
    ios::sync_with_stdio(false);cin.tie();
    int n, m;
    cin >> n >> m;
    vector<pair<int,int>> cd(n);
    for(int i = 0;i < n; i++) cin >> cd[i].first >> cd[i].second;
    // 按照费用从大到小排序
    // 动态规划数组,f[j]表示剩余j点能量时的最大伤害
    vector<int> f(m + 1);
    // 动态规划处理每张卡牌
    for(int i = 0; i < n; i++){
        int c = cd[i].first, d = cd[i].second;
        // 注意:这里的循环方向是从高到低处理能量
        for(int j = c;j <= m; j++){
            // 状态转移:使用当前卡牌后,能量减少c,剩余能量变为(j-c)
            // 然后费用翻倍,相当于剩余能量变为(j-c)/2
        }
    }
    //输出
    i_ak ioi;
}

看到这里你是不是会觉得这个题解很水?那好吧,其实就是很水
好了,完结撒花 ✿✿ヽ(°▽°)ノ✿

6 个赞

给个小赞吧。。。

3 个赞

给了

1 个赞

感谢感谢

我觉得不算特别水吧,该有的也有了

1 个赞

哈哈哈

1 个赞

完蛋了,我绷不住了

嘿嘿嘿

此话题已在最后回复的 15 天后被自动关闭。不再允许新回复。