SZTUOJ 1025.怪物入侵

Description

有 n 个怪物站成一排,编号从 1 到 n 。第i个怪物有 Hi 点生命值。你的攻击力为 a ,你的对手的攻击力为 b ,你和你的对手只能轮流对同一个怪物造成伤害。如果怪物的生命值小于或等于0,则认为它已经死亡,只有当前怪物死亡,你们才可以去挑战其他怪物。如果怪兽死于你的最后一次进攻,你加一分,否则没人加分。你有一种魔法可以迫使你的对手跳过一次攻击。你最多可以使用这个魔法k次。我们保证每次更换怪物的时候,都由你来先手。问如果采取最佳策略,你能获得多少分。

Input

输入的第一行包含四个整数n,a,b和k,分别为怪物的数量,你的攻击力,对手的攻击力和你可以使用魔法的次数。 输入的第二行包含n个整数H1,H2,…,Hn,其中Hi是第i个怪物的生命值。

Output

打印一个整数-如果您使用最佳策略,您可以获得的最多分数。

Sample Input

6 2 3 3
7 10 50 12 1 8

Sample Output

5

Hint

(1 ≤ n ≤ 2*10^5, 1 ≤ a,b,k ≤ 109)(1≤Hi≤109)

Source

SZTU Monthly 2020 Oct.

Author

徒手拆机甲

题目解析

这道题我本来是想用来当这次入门赛的压轴题的。没想到最后过的人比我想的多一些。实际上就是简单模拟题,可以用一个简单的贪心策略就能解决问题。

让我们计算一下杀死每一个怪物所需要的魔法的最小使用次数。让当前怪物拥有h 生命值。首先,很明显我们可以取h模a+b。如果它变成零,我们重新加上a+b。那么我们需要的魔法的使用次数是⌈h/a⌉-1。让我们按这个值对所有n个怪物进行排序,并尽可能杀死所需使用魔法次数少的怪物,其值之和小于或等于k。

⌈⌉符号的意义为向上取整

时间复杂度:O(nlogn)

#include<bits/stdc++.h>
using namespace std;
int f[200005];
int main()
{
long long int n,a,b,k,ans=0;
cin>>n>>a>>b>>k;
for(int i=1;i<=n;i++)
{
cin>>f[i];
f[i]=f[i]%(a+b);
if(f[i]==0)f[i]=a+b;
f[i]=(f[i]-1)/a;//考虑刚好等于a的情况
}
sort(f+1,f+n+1);
for(int i=1;i<=n;i++)
{
if(k>=f[i])
{
ans++;
k-=f[i];
}
else break;
}
cout<<ans<<endl;
return 0;
}
posted @ 2021-06-25 12:08  徒手拆机甲  阅读(126)  评论(0)    收藏  举报