牛客网小白月赛 骑士战胜魔王 01背包和分组背包的结合

题目:https://ac.nowcoder.com/acm/contest/11229/F

题解:https://www.bilibili.com/video/BV1Zv4y1u7hT?p=5&spm_id_from=pageDriver&vd_source=75ae018f8d1181302d7ea76b60c928f4

代码:

复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL power[3010][3010];
LL damage[3010][3010];
LL dp1[3010][3010];//骑士 耗费power的最大伤害
LL dp2[3010][3010];//骑士 伤害大于等于dam的方案
vector<LL> can[3010];
void YD()
{
    LL n, m; cin >> n >> m;
    memset(dp1, -0x3f, sizeof(dp1));
    for (int i = 1; i <= n; i++)
    {
        LL count; cin >> count;
        for (int j = 1; j <= count; j++) cin >> damage[i][j];
        for (int j = 1; j <= count; j++) cin >> power[i][j];
        dp1[i][0] = 0;
        for (int j = 1; j <= count; j++)
        {
            for (int k = 3010; k >= power[i][j]; k--)
            {
                dp1[i][k] = max(dp1[i][k], dp1[i][k - power[i][j]] + damage[i][j]);
            }
        }
        for (int k = 0; k < 3010; k++)
        {
            if (dp1[i][k] >= 0)
                can[i].push_back(k);
        }
    }
    dp2[0][0] = 1;
    LL MOD = 998244353;
    for (int i = 1; i <= n; i++)
    {
        for (int j = m; j >= 0; j--)
        {
            for (int k :can[i])
            {
                if (dp1[i][k] >= 0)
                {
                    dp2[i][j] += dp2[i - 1][max(0LL, j - dp1[i][k])];
                    dp2[i][j] %= MOD;
                }

            }
        }
    }
    cout << dp2[n][m] << endl;


}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T = 1;

    while (T--)
    {
        YD();
    }
    return 0;
}
View Code
复制代码

思路:

  先对每个骑士做一遍01背包,求出消耗某一power的最大伤害

  再对每个骑士做一遍分组背包,此骑士的不同power视为物品组中的物品

  并对当前最大伤害以及物品组中物品造成的伤害进行转移。

posted @   80k  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示