题目背景
@Yumis 出题人在这里哦~
题目描述
Yumis最近在玩炉石传说。
在炉石传说中脏牧有一张一费卡片(一费就是使用要消耗1点法力水晶),叫做疯狂药水,这个的效果是将一个敌方场上攻击小于等于2的随从拉到自己的战场内。
还有一张四费卡片叫做暗影狂乱,这个的效果是将一个敌方场上攻击小于等于3的随从拉到自己的战场内。
还有一张一费卡片就是缩小药水,这个的效果是将敌人全场的随从攻击力下降3点。
你PY了炉石的GM所以你有了无数张的这三种卡片,但是GM告诉你缩小药水是这个牌比较不好创建,为了为GM着想你必须在使用最少的缩小药水的情况下A爆对手的脸。
现在你的对手场上有n个随从,每个随从的攻击力是ki点。
你的对手有m点血量。
而你现在要做的就是将敌方的场上的随从拉过来自己的场上并攻击对手(每一个随从只能攻击一次,攻击力为你拉过来的时候随从剩余的攻击力),A爆对面的脸(将对面的血打到0点及以下)。
输入格式
第一行用一个空格隔开的两个整数n,m分别代表敌方场上的随从数量和你对手的血量。
第二行n个整数每两个整数之间用一个空格隔开,分别代表敌方场上每一个随从的攻击力ki。
输出格式
一行如果可以A爆则输出最少使用的缩小药水的数量和此时使用的法力水晶,两个数据之间用一个空格隔开(如果有多个答案则输出消耗法力水晶最少的答案)。
否则输出“Human Cannot Win Dog”(没有双引号)
输入输出样例
3 5 1 2 3
0 5
8 8 10 20 30 40 50 60 70 80
16 23
8 80 10 20 30 40 50 60 70 80
Human Cannot Win Dog
说明/提示
样例说明1:
敌方场上有3只随从,敌方有5点血量
我们把3攻随从和2攻随从拉过来花费0个缩小药水和5点耗费(一张疯狂药水一个暗影狂乱(1+4 = 5))伤害足够击杀对方。
样例说明2:
使用16个缩小药水(下面数据后面第一个括号指拉过来的时候伤害为多高 ,第二个括号表示拉过来的时候使用多少的缩小药水)
拿10(1)(3)、20(2)(6)、30(3)(9)、50(2)(16)攻的怪物总共造成8点伤害 刚好A爆!
Easy : 保证 0 < n <= 10 并且不存在用到暗影狂乱和缩小药水的情况 20%
Normal :保证 0 < n <= 10 并且不存在用到缩小药水的情况 20%
Hard :保证 0 < n <= 10 30%
Extra:保证0 <= n <= 5000000(6个0),最大攻击力小于30000 30%
保证 0 < n <= 5000000 0 < ki <=30000 0<=m<=5000000 (6个0)
存在用以下代码可以拿到10分的情况
#include<cstdio>
int main ()
{
printf(“Human Cannot Win Dog”);
return 0;
}
和以下该代码也可以拥有10分
#include<cstdio>
int main ()
{
printf(“0 0”);
return 0;
}
那么怎么办呢?
瞄一眼最大攻击力的范围,发现只有3000030000,于是瞬间想法就有了——桶排!
首先开一个桶k[30000+...]k[30000+...],之后就可以桶排了
#include<cstdio> #include<iostream> #include<fstream> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define Set(a) memset(a,0,sizeof(a)) #define F(i,a,b) for(register int i=a;i<=b;++i) #define UF(i,a,b) for(register int i=a;i>=b;--i) #define openf(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout) typedef long long LL; typedef long long ll; typedef unsigned long long ULL; typedef unsigned long long ull; inline int read(int &x) { int f = 1; x = 0; char ch = getchar(); for(;!isdigit(ch); ch = getchar()) if(ch == '-') f = -1; for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48; return x *= f; } inline ll readll(ll &x) { int f = 1; x = 0; char ch = getchar(); for(;!isdigit(ch); ch = getchar()) if(ch == '-') f = -1; for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48; return x *= f; } typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef long double ld; typedef double dou; #define mp(a,b) make_pair(a,b) inline int max(int a,int b){return a>b?a:b;} inline int min(int a,int b){return a<b?a:b;} const int inf=1<<30; int n,m; namespace d1{ int a[15]={}; void init(){F(i,1,n) read(a[i]);} void solve() { int anst=inf,answ=inf; int s,t,w; F(i,0,(1<<n)-1) { s=t=w=0; F(j,1,n) if((i&(1<<(j-1)))!=0) { s+=(a[j]-1)%3+1; if(a[j]%3==0) t+=4;else ++t; w=max(w,(a[j]-1)/3); } if(s>=m&&w<=answ) {answ=w;anst=min(anst,t);} } if(answ==inf) printf("Human Cannot Win Dog"); else printf("%d %d",answ,anst+answ); return; } } #define ff(a,b) k[3*a+b] namespace d2{ int k[30000+10]={},x; void init() { F(i,1,n) {read(x);++k[x];} } void solve() { int q[5]={},t,x,i; bool ok=false; for(i=0;i<=9999;++i) { q[1]+=ff(i,1); q[2]+=ff(i,2); q[3]+=ff(i,3); if(q[1]+2*q[2]+3*q[3]>=m) {ok=true;break;} } if(!ok)printf("Human Cannot Win Dog"); else { x=q[1]+2*q[2]+3*q[3]; t=min(q[3],(x-m)/3); q[3]-=t;x-=3*t; t=min(q[1],x-m); q[1]-=t;x-=t; t=min(q[2],(x-m)/2); q[2]-=t;x-=2*t; printf("%d %d",i,i+q[1]+q[2]+4*q[3]); } return; } } int main() { read(n);read(m); if(n<=10) {d1::init();d1::solve();} else {d2::init();d2::solve();} return 0; }