瓜皮的佳木斯集训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,X22X1,X2≤2

对于100%的数据,T100T≤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 }
legend

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%的数据,n10n≤10,m20m≤20

对于另外30%的数据,gi=0gi=0

对于100%的数据,n10000n≤10000,m100000m≤100000, 0<G,S10000<G,S≤1000 , gi10gi≤10,si1000si≤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 }
worry

 

 


以上是关于瓜皮的佳木斯集训Day1的主要内容,如果未能解决你的问题,请参考以下文章

2021年SWPUACM暑假集训day1二分算法

#6030. 雅礼集训 2017 Day1矩阵

暑假集训day1

矩阵[雅礼集训 2017 Day1]

奇数国[清华集训2014 Day1]

2017雅礼集训 Day1