这个题题目的意思很好懂;就是有n个怪兽,他们各自的Hp和Atk都给了;然后一个英雄去kills这些Monsters;
但是有个规则:就是该英雄对一个怪物,他对怪物的伤害是随着攻击次数增加的;也就是等差数列(第一次为1点伤害,第二次为2点伤害,第三次为3点伤害…);但是在英雄攻击怪物之前他会被所有的怪物攻击;并且受到的损伤是所有怪物的攻击力之和;然后求kill所有怪物的情况下英雄的受伤值最小是多少;
其实这道题我刚开始被案例带偏了;我直接按照Atk排个序,然后求每个的攻击次数就完了(因为我觉得需要把Atk最大的先干掉);结果就是wa了;后来队友想了想;他举了一个例子:
右边的就是反例;如果只考虑把Atk高的先kill掉,那么右边的例子就是21;很明显这个有问题;因为答案为19;因为我可以先把2kill掉;所以我就不应该这样想了;后来发现这个问题;如果我把对英雄平均伤害大的先kill掉不就可以了吗?意思就是:
每个monster对应的Atk值/他被kill掉的次数;那么不就是平均每次对英雄造成伤害大的吗?所以直接求出这个比值,那后sort一下最后算一算次数就AC了;因为这个我还wa了两次,无语了QAQ;总得来说就是去找每次对英雄伤害比较大的怪物,然后kill它,只不过这个平均值还真的不好想;感觉有点像挑战设计上面的最大化平均值一样;所以就是(Atk/需要被干掉的次数)这个值排个序就AC了;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Monster{
ll hp,ak;
double Cmp;
}p[100050];
bool cmp(Monster a,Monster b){//这里用来排序,从大到小
return a.Cmp>b.Cmp;
}
int main(){
ll T;
cin>>T;
ll n;
ll ans,all;
ll g=1;
while(T--){
ans=0;
all=0;
cin>>n;
for(ll i=0;i<n;i++){
cin>>p[i].hp>>p[i].ak;
all+=p[i].ak;
}
for(ll i=0;i<n;i++){
ll tt=ceil((-1+sqrt(1+8.0*p[i].hp))/2.0);//这里需要向上取整,因为如果hp为4,那么你算出来的n就是2.几,所以你需要3次kill这个怪物;这里是求根公式,求的是kill这个怪物的次数
p[i].Cmp=p[i].ak*1.0/tt; //这里是求比值
}
sort(p,p+n,cmp);
//for(int i=0;i<n;i++)cout<<p[i].Cmp<<" ";
for(ll i=0;i<n;i++){
ll tt=ceil((-1+sqrt(1+8.0*p[i].hp))/2.0);
ans+=tt*all;
all-=p[i].ak;
}
printf("Case #%lld: %lld\n",g++,ans);
}
return 0;
}