1. 程式人生 > >[洛谷 P3239] [HNOI2015]亞瑟王

[洛谷 P3239] [HNOI2015]亞瑟王

出了 lap 體驗 希望 scan 可能 遊戲 兩個 排列

[HNOI2015]亞瑟王

題目描述

小 K 不慎被 LL 邪教洗腦了,洗腦程度深到他甚至想要從亞瑟王邪教中脫坑。他決定,在脫坑之前,最後再來打一盤亞瑟王。既然是最後一戰,就一定要打得漂亮。眾所周知,亞瑟王是一個看臉的遊戲,技能的發動都是看概率的。

作為一個非洲人,同時作為一個前 OIer,小 K 自然是希望最大化造成傷害的期望值。但他已經多年沒寫過代碼,連 Spaly都敲不對了,因此,希望你能幫幫小 K,讓他感受一下當歐洲人是怎樣的體驗。

本題中我們將考慮遊戲的一個簡化版模型。 玩家有一套卡牌,共 n張。遊戲時,玩家將 n 張卡牌排列成某種順序,排列後將卡牌按從前往後依次編號為 1 ~ n。本題中,順序已經確定,即為輸入的順序。每張卡牌都有一個技能。第 i 張卡牌的技能發動概率為 pi,如果成功發動,則會對敵方造成di點傷害。也只有通過發動技能,卡牌才能對敵方造成傷害。基於現實因素以及小K非洲血統的考慮,pi不會為 0,也不會為 1,即 0 < pi < 1。 一局遊戲一共有 r 輪。在每一輪中,系統將從第一張卡牌開始,按照順序依次考慮每張卡牌。在一輪中,對於依次考慮的每一張卡牌:

1如果這張卡牌在這一局遊戲中已經發動過技能,則

1.1 如果這張卡牌不是最後一張,則跳過之(考慮下一張卡牌); 否則(是最後一張),結束這一輪遊戲。

2否則(這張卡牌在這一局遊戲中沒有發動過技能),設這張卡牌為第 i 張

2.1將其以 pi的概率發動技能。

2.2如果技能發動,則對敵方造成 di點傷害,並結束這一輪。

2.3如果這張卡牌已經是最後一張(即 i 等於n),則結束這一輪;否則,考慮下一張卡牌。

請幫助小 K 求出這一套卡牌在一局遊戲中能造成的傷害的期望值。

輸入輸出格式

輸入格式:

輸入文件的第一行包含一個整數 T,代表測試數據組數。 接下來一共 T 組數據。 每組數據的第一行包含兩個用空格分開的整數 n和r,分別代表卡牌的張數和遊戲的輪數。 接下來 n行,每行包含一個實數和一個整數,由空格隔開,描述一張卡牌。第i 行的兩個數為 pi和 di,分別代表第 i 張卡牌技能發動的概率(實數)和技能發動造成的傷害(整數)。保證 pi最多包含 4位小數,且為一個合法的概率。

輸出格式:

對於每組數據,輸出一行,包含一個實數,為這套卡牌在這一局遊戲中造成的傷害的期望值。對於每一行輸出,只有當你的輸出和標準答案的相對誤差不超過10^-8時——即|a-o|/a<=10-8時(其中a是標準答案,o是輸出),你的輸出才會被判為正確。建議輸出10 位小數。

輸入輸出樣例

輸入樣例#1:
1
3 2
0.5000 2
0.3000 3
0.9000 1
輸出樣例#1:
3.2660250000

說明

一共有 13 種可能的情況:

  1. 第一輪中,第 1張卡牌發動技能;第二輪中,第 2張卡牌發動技能;

概率為 0.15,傷害為5。

  1. 第一輪中,第 1張卡牌發動技能;第二輪中,第 3張卡牌發動技能;

概率為 0.315,傷害為3。

  1. 第一輪中,第 1張卡牌發動技能;第二輪不發動技能;

概率為 0.035,傷害為2。

  1. 第一輪中,第 2張卡牌發動技能;第二輪中,第 1張卡牌發動技能;

概率為 0.075,傷害為5。

  1. 第一輪中,第 2張卡牌發動技能;第二輪中,第 3張卡牌發動技能;

概率為 0.0675,傷害為4。

  1. 第一輪中,第 2張卡牌發動技能;第二輪不發動技能;

概率為 0.0075,傷害為3。

  1. 第一輪中,第 3張卡牌發動技能;第二輪中,第 1張卡牌發動技能;

概率為 0.1575,傷害為3。

  1. 第一輪中,第 3張卡牌發動技能;第二輪中,第 2張卡牌發動技能;

概率為 0.04725,傷害為4。

  1. 第一輪中,第 3張卡牌發動技能;第二輪不發動技能;

概率為 0.11025,傷害為1。

  1. 第一輪不發動技能;第二輪中,第 1張卡牌發動技能;

概率為 0.0175,傷害為2。

  1. 第一輪不發動技能;第二輪中,第 2張卡牌發動技能;

概率為 0.00525,傷害為3。

  1. 第一輪不發動技能;第二輪中,第 3張卡牌發動技能;

概率為 0.011025,傷害為1。

  1. 第一輪不發動技能;第二輪亦不發動技能;

概率為 0.001225,傷害為0。

造成傷害的期望值為概率與對應傷害乘積之和,為 3.266025。

對於所有測試數據, 1 <= T <= 444, 1 <= n <= 220, 0 <= r <= 132, 0 < pi < 1, 0 <= di <= 1000。

除非備註中有特殊說明,數據中 pi與di均為隨機生成。

請註意可能存在的實數精度問題,並采取適當措施。

做了這題發現自己實在是太弱了......被狂虐......

當我忍不住看了各路dalao的題解後,搞了好久才搞懂......

用各路dalao的說法,這題的難點就是約束條件很坑,每張牌最多只能用一次,且如果出了某張牌,這一輪就結束了,這個條件很無奈...

dalao們教我將R倫看成R個機會,每一張牌對每一個機會都有一定的概率可以拿,最後要求出收益的期望.

那麽,我們設f[i][j]表示第i張牌獲得了j次機會的概率.那麽有兩種情況:

f[i+1][j]+=f[i][j]*(1-p[i])^j(即第i張牌並沒有在j輪內打出的概率,即把每一輪都不打出的概率相乘得到)

f[i+1][j-1]+=f[i][j]*(1-(1-p[i])^j)(即第i張牌在j輪內打出的概率)

最後枚舉每一個(i,j),ans+=f[i][j]*(1-(1-p[i])^j)*d[i].

技術分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 using namespace std;
 6 const int maxn=305;
 7 int n,rnd,D[maxn];
 8 double P[maxn],f[maxn][maxn],pw[maxn][maxn],ans;
 9 int main(){
10     int Tt; scanf("%d",&Tt);
11     for (int Ts=1; Ts<=Tt; Ts++){
12         scanf("%d%d",&n,&rnd);
13         for (int i=1; i<=n; i++) scanf("%lf%d",&P[i],&D[i]);
14         for (int i=1; i<=n; i++){
15             pw[i][1]=1.0-P[i];
16             for (int j=2; j<=rnd; j++) pw[i][j]=pw[i][j-1]*(1.0-P[i]);
17         }
18         memset(f,0,sizeof f),f[1][rnd]=1,ans=0;
19         for (int i=1; i<n; i++)
20             for (int j=1; j<=rnd; j++) f[i+1][j]+=f[i][j]*pw[i][j],f[i+1][j-1]+=f[i][j]*(1-pw[i][j]);
21         for (int i=1; i<=n; i++)
22             for (int j=1; j<=rnd; j++) ans+=f[i][j]*(1-pw[i][j])*D[i];
23         printf("%.10lf\n",ans);
24     }
25     return 0;
26 }
View Code

我太弱了......

[洛谷 P3239] [HNOI2015]亞瑟王