瓜皮的佳木斯集訓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 }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%的數據,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 }worry
瓜皮的佳木斯集訓Day1