瓜皮的佳木斯集训Day1
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了瓜皮的佳木斯集训Day1相关的知识,希望对你有一定的参考价值。
T1:“疲劳”传说
炉石传说:魔兽英雄传是一款由暴雪开发的非常流行的游戏。这个问题建立在这个游戏的基础上,但是即使你不知道这个游戏,你也能非常轻松的解决这个问题。
每一局游戏是两个对手1v1的比赛。炉石传说的游戏方式是回合制,每个玩家轮流打出自己手中的牌。
每个玩家可以选择一个“英雄”,一个魔兽争霸中的重要人物。每个英雄有它独特的英雄技能。每个英雄有30滴血,并且如果他的血量减少到0 以下(包括0),英雄就会死亡、控制他的玩家就输掉了游戏。
在回合开始,玩家需要从他们的牌库中抽一张卡——牌库由玩家在游戏前挑选好的30张牌组成。在回合中,玩家可以选择使用卡牌或是使用英雄技能。然而,他们的行动将会消耗法力水晶,这个限制促使玩家策略性地规划他们的行动。每个玩家由1个法力水晶开局,在他们每个回合的开始都会多获得一个新的空法力水晶直到达到10个法力水晶的上限,并且将恢复所有法力水晶。
然而,一旦一个玩家抽光了他的牌库,从空牌库中抽卡会导致他们受到“疲劳”的伤害。“疲劳”在刚开始对玩家造成1点伤害,但是每次伤害都会加1。
注意,即使牌库为空也必须抽卡,即牌库为空后每回合都需要受到“疲劳”的伤害
现在,考虑这样一种情况:玩家手中的卡已经用完,两个玩家都有10个法力水晶上限,并且每个玩家在回合开始时都会获得10个法力水晶。
那意味着,每回合,每个玩家需要按顺序执行两个操作:
(1) 从空牌库中抽卡
(2) 使用他们的英雄技能(英雄技能消耗两个法力水晶并且每回合只能使用一次)
定义nn为英雄的血量,nn不超过30。
定义mm为英雄的护甲,只有当英雄的护甲降为0时才会减少英雄的血量。英雄护甲没有上限。
注意,这里的护甲属于"消耗品",即如果受到伤害使护甲减少,护甲在这之后都不会恢复。
为了简化问题,我们给出四个英雄可供选择:
1 吉安娜 火焰冲击 对任意目标造成一点伤害
2 雷克萨 稳固射击 对敌方英雄造成两点伤害
3 加尔鲁什 全副武装 获得两点护甲
4 安度因 次级治疗术 回复两滴血
给你两个玩家的英雄编号,英雄血量,英雄护甲,两个英雄都按照最优策略行动,请问第一个玩家能获胜吗?(假设两人还未受到“疲劳”伤害)
注意:英雄的血量不能超过其上限30。
输入格式
第一行包括整数TT表示包含TT组数据。
对于每组数据:第一行包括三个整数X1X1,N1N1,M1M1,代表第一个玩家的英雄编号,英雄血量与英雄护甲。
第二行包括三个整数X2X2,N2N2,M2M2代表第二个玩家的英雄编号,英雄血量与英雄护甲。
输出格式
对于每组数据,如果第一个玩家能获胜,输出“YES”,否则输出“NO”
样例
Input
2
1 10 3
2 5 10
3 10 10
4 10 10
Output
NO
NO
explanation
无可奉告。
数据范围与约定
对于50%的数据,X1,X2≤2X1,X2≤2
对于100%的数据,T≤100T≤100,保证输入数据合法且运算过程中所有数不超过32位整数
时间限制:1s
空间限制:128M
题解:纯粹的模拟题,需要注意以下几点:
1,每次造成伤害都要判定死亡;
2,牧师无法将血恢复到30以上,装甲先承受伤害
3,疲劳清零!!!
测试的时候不少人都中了招,遇到这种事哭都找不到地方
以下是我的程序
1 #include<cstdio> 2 using namespace std; 3 int main(){ 4 int a,b,c,i,j,n,h; 5 int X1,X2,N1,N2,M1,M2,hurt,T; 6 // freopen("legend.in","r",stdin); 7 // freopen("legend.out","w",stdout); 8 scanf("%d",&T); 9 for(i=1;i<=T;i++){if(i!=1)printf("\n");hurt=0; 10 scanf("%d%d%d",&X1,&N1,&M1); 11 scanf("%d%d%d",&X2,&N2,&M2); 12 while((N1!=0)&&(N2!=0)){hurt++; 13 M1-=hurt; 14 if(M1<=0){N1+=M1;M1=0;} 15 if(N1<=0){printf("NO");break;} 16 if(X1==1) 17 {M2-=1;if(M2<=0) 18 {N2+=M2;M2=0;}} 19 else if(X1==2) 20 {M2-=2;if(M2<=0) 21 {N2+=M2;M2=0;}} 22 else if(X1==3)M1+=2; 23 else{N1+=2;if(N1>=30)N1=30;} 24 if(N2<=0) 25 {printf("YES");break;} 26 M2-=hurt; 27 if(M2<=0){N2+=M2;M2=0;} 28 if(N2<=0){printf("YES");break;} 29 if(X2==1) 30 {M1-=1;if(M1<=0) 31 {N1+=M1;M1=0;}} 32 else if(X2==2) 33 {M1-=2;if(M1<=0) 34 {N1+=M1;M1=0;}} 35 else if(X2==3)M2+=2; 36 else {N2+=2;if(N2>=30)N2=30;} 37 if(N1<=0) 38 {printf("NO");break;} 39 } 40 } 41 }
T2:国王的烦恼
Ukinojs国疆域辽阔,城邦众多。但是丰饶的土地不仅富足了人们的生活,也吸引来了一伙强盗。强盗分散在Ukinojs国的各条交通干线上,在不同道路上的强盗对金币和银币有着不同的需求。金币和银币是Ukinojs国的两种货币,每一个单位的金币和银币所代表的财富值分别为GG和SS。
虽然每条道路上的强盗需求各不相同,但是他们都有着自己的小脾气。他们不能容忍其他的强盗获得比自己数量更多的金币和银币。
国王因此感到十分的烦恼,他既不想让强盗影响自己国家的交通(即保证国家内的各个城市必须相互联通),又想耗费尽可能少的财富值,于是国王找到了你,希望你能告诉他,至少要花费多少财富值,才能使国家的交通重新恢复正常。
输入格式
第一行包括四个整数:nn,mm,GG,SS;分别表示王国中城市的数量,城市间路径的个数,金币所代表的财富值,银币所代表的财富值。
接下来mm行,每行4个整数uu,vv,gigi,sisi;表示一条连接uu和vv的路径,占据这条路的强盗的需求为gigi个金币和sisi个银币。
输出格式
一行一个整数,表示最少需要花费的财富值。
样例1
Input
4 4 2 1
1 3 1 2
1 2 1 3
2 4 2 1
1 4 3 2
Output
21
explanation
最优答案为选择(1,3)(1,3),(1,2)(1,2),(2,4)(2,4)这三条路,至少需要提供给每个强盗的金币为max(1,1,2)=2max(1,1,2)=2个,银币为max(2,2,3)=3max(2,2,3)=3个,花费的财富值为2×2+3×1=72×2+3×1=7。因为只需赶走这3条路径上的强盗即可恢复交通,所以需7×3=217×3=21财富值即可。
样例2
Input
4 4 1 2
1 3 1 2
1 2 1 3
2 4 2 1
1 4 3 2
Output
21
explanation
最优答案为选择(1,3)(1,3),(1,4)(1,4),(2,4)(2,4)这三条路,至少需要提供给每个强盗的金币为max(1,3,2)=3max(1,3,2)=3个,银币为max(2,2,1)=2max(2,2,1)=2个,花费的财富值为3×1+2×2=73×1+2×2=7。因为只需赶走这3条路径上的强盗即可恢复交通,所以需7×3=217×3=21财富值即可。
数据范围与约定
对于30%的数据,n≤10n≤10,m≤20m≤20
对于另外30%的数据,gi=0gi=0
对于100%的数据,n≤10000n≤10000,m≤100000m≤100000, 0<G,S≤10000<G,S≤1000 , gi≤10gi≤10,si≤1000si≤1000,保证存在一种使得所有城市联通的方案
时间限制:1s
空间限制:128M
题解:典型的克鲁斯卡尔,但是有两个权值,将两个权值转化成一个权值(财富)虽然是错的,但能拿挺多分(数据太水),看到金币≤10就想到可以枚举金币建树(11次)
以下是代码(我太瓜只能拿80,贴的是标程):
1 #include <cstdio> 2 #include <algorithm> 3 #define N 10005 4 #define INF 100000000000ll 5 using namespace std; 6 typedef long long LL; 7 struct Edge{ 8 int u,v,gold,silver; 9 bool operator < (const Edge& rhs)const{return silver<rhs.silver;} 10 }e[N*10]; 11 bool cmp(const Edge& x,const Edge& y){return x.gold<y.gold;} 12 13 int n, m, G, S; 14 int M, pa[N]; 15 int root(int x){return pa[x] == x ? pa[x] : pa[x]=root(pa[x]);} 16 LL ans = INF; 17 18 int Kruskal() { 19 for(int i=1;i<=n;i++)pa[i]=i; 20 int i,cnt=0; 21 for(i = 1; i < M; i++) { 22 int pa_x=root(e[i].u),pa_y =root(e[i].v); 23 if(pa_x==pa_y)continue; 24 pa[pa_x]=pa_y; 25 cnt++; 26 if(cnt==n-1) break; 27 } 28 if(cnt<n-1)return-1; 29 return e[i].silver; 30 } 31 int main() { 32 scanf("%d%d%d%d",&n,&m,&G,&S); 33 for(int i=1;i<=m;i++)scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].gold,&e[i].silver); 34 sort(e+1,e+1+m,cmp); 35 M=1; 36 for(int i=0;i<=10;i++) { 37 while(e[M].gold<=i && M<=m)M++; 38 sort(e+1,e+M); 39 int silver_cost=Kruskal(),gold_cost = i; 40 if(silver_cost!=-1)ans=min(ans,(LL)silver_cost*S+gold_cost*G); 41 } 42 printf("%lld\n",ans*(n-1)); 43 return 0; 44 }
以上是关于瓜皮的佳木斯集训Day1的主要内容,如果未能解决你的问题,请参考以下文章