nyoj1598——卡牌游戏(hearth) (DP)

本文介绍了一种基于卡牌游戏的策略算法,旨在帮助玩家通过最优顺序使用卡牌,在限定回合内击败对手。通过动态规划和排序技巧,算法确定了在不同情况下所需的最少卡牌数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

  zyb 迷上了一款卡牌游戏。在卡牌游戏中,每张卡牌有两个属性:伤害和法强加成。在一 回合中,zyb 每打出一张伤害为 a,法强加成为 b 的卡牌,将会依次产生以下效果:  

  • zyb 对敌方造成 x + a 点伤害(即敌方的生命值减少 x + a),其中 x 为 zyb 当前的法术 强度;   

  • zyb 的法术强度增加 b。  

  现在轮到了 zyb 的回合,他拥有 n 张卡牌,初始时 zyb 的法强值为 0,敌方的生命值为 k。 zyb 希望按一定顺序打出手里的卡牌,使得敌方的生命值降低到 0 或更低。  

  你需要帮助 zyb 判断,他是否可能在当前回合击杀敌方。如果可以,你还要帮 zyb 求出他 最少使用多少张手牌,才可以击杀敌方。  

 

输入描述:

第一行 2 个正整数 n, k (1 ≤ n ≤ 3000, 1 ≤ k ≤ 1015),表示 zyb 手中的卡牌数以及敌方的初始生命值。

接下来的 n 行,每行包含 2 个正整数 a, b (1 ≤ a, b ≤ 1000000),分别表示的第 i 张卡牌的伤害和法强加成。

输出描述:

输出一行一个正整数,表示答案。

如果 zyb 可以用手里的卡牌在当前回合消灭敌方,输出打出卡牌数的最小值;如果不可以,输出 impossible。

样例输入:

复制

3 10
4 1
1 6
2 4

样例输出:

2

思路:如果确定了牌,那么这些牌一定是按法强从大到小打出的,所以需要先排好序。确立dp状态,i,j代表在第i张牌时,选择j张牌能打出的最大伤害。dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+A[i].b*(j-1)+A[i].a);

#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<utility>
using namespace std;
long long n,m;
long long dp[3010][3010];
struct node
{
    long long a,b;
    bool operator <(const node &B)const
    {
        return this->b<B.b;
    }
}A[3010];
int main()
{
    int flag=0;
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&A[i].a,&A[i].b);
    sort(A+1,A+n+1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+A[i].b*(j-1)+A[i].a);
    for(int i=1;i<=n;i++)
    {
        if(dp[n][i]>=m)
        {
            flag=1;
            printf("%lld\n",i);
            break;
        }
    }
    if(!flag)
        printf("impossible\n");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值