Description
众所周知,小J和小G是死对头,一天小G带领一群小弟找到了小J。
问题描述
小G有n个小弟,第i个小弟有ai点攻击力,小G有m点血量。
小J在小G找小第的时间里去找小Z学到了膜法,他在大战前配置了三种魔法药水
1:复用型药水:花费1法力值,选择小G的攻击力小于等于2的一个小弟让他跟随自己(变为自己的小弟并且攻击力和属于小G时一样)
2:猎人药水:花费4法力值,选择小G的攻击力小于等于3的一个小弟让他跟随自己
3:腐败药水:花费1法力值,使小G所有小弟攻击力降低三点(使用前两种魔法将小弟拉到自己阵营时小弟攻击力就是当前的攻击力,即小J的小弟攻击力只能为1,2,3)
为了向小G展现自己的力量,他打算在召集到一些小弟后发动攻击(每个小弟打一次)直接秒杀小G(攻击力大于等于m)
由于智商有限,小J在配置腐败药水时会花费很大精力,他需要知道自己最少使用多少腐败药水,并在腐败药水数量最小的情况下花费最小的法力值
Input
第一行两个正整数n,m表示小G的小弟数量和血量
第二行n个正整数表示小G所有小弟的攻击力
Output
一行两个整数表示最小的腐败药水数量和在腐败药水最小的情况下法力值花费,如果无论如何都无法战胜,输出一个整数-1
Sample Input
Sample Input1:
3 5
1 2 3
Sample Input2:
8 8
10 20 30 40 50 60 70 80
Sample Input3:
8 80
10 20 30 40 50 60 70 80
Sample Output
Sample Output1:
0 5
样例说明
对2,3小弟使用复用型药水和猎人药水
Sample Output2:
16 23
样例说明
使用16个腐败药水
在第3个腐败药水时拉10,攻击力为1
在第6个腐败药水时拉20,攻击力为2
在第9个腐败药水时拉30,攻击力为3
在第16个腐败药水时拉50,攻击力为2
Sample Output3:
-1
Data Constraint
数据规模和约定
测试点1,2: n≤10并且最优情况不需要使用腐败药水和猎人药水
测试点3,4: n≤10并且最有情况不需要使用腐败药水
测试点5,6,7: n≤10
测试点8,9,10: n≤5000000,最大攻击力小于等于30000
对于所有数据 0≤m≤5000000
Hint
提示
鉴于本题为签到题直接输出-1或者0,0都能获得10分的好成绩
请仔细阅读题目,有些细节可能让你损失很多的分数0.0
输入规模较大,请使用较快的读入方式
思路
PS:这题千万不要用快读!!!会出事!!!
这题是贪心。。。
首先我们可以用桶排排序,然后枚举使用腐败药水的个数,直到综合大于等于m
然后贪心去掉一些东西即可
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,at1,at2,at3,ans,p=-1,a[30077],t=0;
int main()
{
freopen("zhanshajihua.in","r",stdin); freopen("zhanshajihua.out","w",stdout);
scanf("%d%d",&n,&m);
if(m==0)
{
printf("0 0"); return 0;
}
for(int i=1; i<=n; i++)
{
int x;
scanf("%d",&x); a[x]++;
int xx=x%3==0?3:x%3; t+=xx;
}
if(t<m)
{
printf("-1"); return 0;
}
int s=0;
for(int i=1; i+2<=30001; i+=3)
{
ans+=a[i]; at1+=a[i];
ans+=a[i+1]*2; at2+=a[i+1];
ans+=a[i+2]*3; at3+=a[i+2];
p++;
if(ans>=m) break;
}
while(ans>=m+3&&at3) {at3--; ans-=3;}
while(ans>=m+1&&at1) {at1--; ans-=1;}
while(ans>=m+2&&at2) {at2--; ans-=2;}
printf("%d %d",p,(at1+at2)+at3*4+p);
}