题目描述:
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");
}