题目描述
小 X 穿越到了异世界,国王命令他招揽勇士,杀死恶龙,救回公主。
异世界是高度数据化的。恶龙有一个攻击力 ATK,一个生命值 HP。类似的,每个勇士也有一个攻击力 Ai,一个生命值 Hi。
战斗是回合制的,并且每次只能由一个勇士和恶龙单挑。战斗中,每个回合恶龙的生命值会减去这个勇士的攻击力,这个勇士的生命值会减去恶龙的攻击力。
如果回合结束的时候恶龙的生命值小于等于 0,那么恶龙就被杀死了;如果这个勇士的生命值小于等于 0,那么这个勇士就被击败了,需要换上另一个勇士继续战斗。当然,如果恶龙还没有被杀死,勇士却全部被击败了,那么这场战役就彻底失败了。
不过聪明的小 X 安排了一个特殊的战术:在一名勇士被击败后立刻让另一名勇士发起攻击,这样恶龙在勇士们的车轮战术下疲于招架,受到第二个勇士的伤害变为两倍,受到第三个勇士的伤害变为三倍……以此类推。
现在一共有 n 名勇士报名,小 X 想问问你,如果合理安排勇士出战的顺序,最少要招揽多少名勇士才能杀死恶龙?
输入
第一行为一个正整数 n,表示一共有 n 名勇士报名。
第二行两个正整数 ATK 和 HP 表示恶龙的攻击力和生命值。
接下来共有 n 行,每行两个正整数 Ai 和 Hi 表示这名勇士的攻击力和生命值。
输出
输出一个整数,表示最少要招揽多少名勇士才能杀死恶龙。
如果不可能杀死恶龙,输出”Fail”。
样例输入
2
1 9
2 2
1 1
样例输出
2
样例解释
样例解释
两名勇士都招揽。先派出 2 号勇士
第一回合,恶龙生命值变为 8,勇士生命值变为 0。勇士被击败
紧接着派出 1 号勇士
第二回合,恶龙生命值变为 4(两倍伤害),勇士生命值变为 1
第三回合,恶龙生命值变为 0,勇士生命值变为 0。恶龙被杀死
勇士虽然也被击败了,但恶龙已经死了,所以还是胜利了!
数据范围
本题共有 10 个测试点,每个测试点 15 分
对于测试点 1-4 :n<=5,ATK,Hi,Ai<=10,HP<=100
对于测试点 5-7 :n<=1000,ATK,Hi,Ai<=1000,HP<=10^9
对于测试点 8-10 :n<=105,ATK,Hi,Ai<=106,HP<=10^18
思路历程
我最开始看到这个题的时候,第一反应就将所有勇士按照伤害的大小进行排序,伤害低的放前面,伤害高的放后面。这样就可以保证所有勇士的造成伤害最大化。更容易击杀恶龙,但是这只是造成伤害最大的情况,题目要求的是求出能杀死恶龙的最少人数。
但是考虑到这种情况:
假如勇士的队伍里有一个非常NB的勇士,那么根本不需要其他小喽喽给他做铺垫,他自己就可以独自解决饿龙了。
所以我改变了一下思路:
我将伤害高的排在前面,伤害低的排在后面,然后从左向右选人并且出战。试试能不能用这种方法把恶龙秒了!就不需要那么多人了!
但是我发现了一组样例又能hack掉我这样的计算方式
hack 样例:
假如恶龙 攻击力 1 生命值 25
3名勇士: 10 1
5 1
4 1
如果按照上述错误的排序,需要3个人才能解决
但是实际上只需要两个人。
这样的方法会使总体的造成伤害过低,遇到高生命值的恶龙反倒需要更多人
正确的思路(避免看废话)
那有什么办法能让伤害又高,上阵的人又少呢?
让勇者们按照实际能造成伤害的高低排序
然后从能造成伤害高的开始一个一个选。
先选出来的勇者后上阵 。(保证总伤害最高)
一个勇者能造成的伤害=勇者输出的次数*勇者的攻击力(没经过新战术提升的情况下)
AC代码:
#include<bits/stdc++.h>
using namespace std;
struct Stu
{
long long hp;//生命值 !
long long gong;// 攻击力!
long long shiji;//实际上能造成伤害的多少!
}stu[100001];
bool cmp(Stu x,Stu y)
{
return x.shiji<y.shiji;
}
int main()
{
long long n;
cin>>n;
long long bossgong;
long long bosshp;
cin>>bossgong>>bosshp;
for(int i=1;i<=n;i++)
{
cin>>stu[i].gong;
cin>>stu[i].hp;
int h=stu[i].hp/bossgong;
int g=stu[i].hp%bossgong;
if(g!=0)
h++;
stu[i].shiji=h*stu[i].gong;
}
sort(stu+1,stu+1+n,cmp);
//for(int i=1;i<=n;i++)
// {
// cout<<stu[i].gong<<" "<<stu[i].hp<<" "<<stu[i].shiji<<endl;
//}
long long sum=0;
long long ans;
long long num=0;
long long temp=0;
int flag=0;
for(int u=n;u>=1;u--)
{
sum=sum+temp;
sum+=stu[u].shiji;
temp+=stu[u].shiji;
//cout<<sum<<endl;
num++;
if(sum>=bosshp)
{
ans=num;
flag=1;
break;
}
}
if(flag==1)
cout<<ans;
else
printf("Fail");
return 0;
}
本代码详细的模拟过程(也是废话)
样例
:假如恶龙 攻击力 1 生命值 25
3名勇士: 10 1
5 1
4 1
排序之后:4 1 5 1 10 1
开始选人:10 1 →造成伤害 10点+0点+0点=10点 (恶龙没死,继续向左选人)
5 1→造成伤害:5点+10点+10点(由于先选的人后上阵,上一个勇者的攻击提升10点) =25点!
4 1 →造成伤害: 4点+25点+15点= 44点!
所以根据上述模拟可知,2个人 就可以把恶龙杀死了!
并且这种情况是伤害最多情况下的选人最少,符合条件!
其中:4是本回合新选的勇士的伤害,25是上次选人的伤害
15是之前选过的所有勇士伤害的提升值!
加起来就是勇士们的总伤害了!
2021/5/23