1. 程式人生 > >瓜皮的佳木斯集訓Day1

瓜皮的佳木斯集訓Day1

out opera legend kruskal 按順序 重新 10個 src ons

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