bzoj4008: [HNOI2015]亞瑟王

題目鏈接

bzoj4008

題目描述

Description

小 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 求出這一套卡牌在一局遊戲中能造成的傷害的期望值。

Input

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

Output

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

Sample Input

1
3 2
0.5000 2
0.3000 3
0.9000 1

Sample Output

3.2660250000

HINT

一共有 13 種可能的情況:
1. 第一輪中,第 1張卡牌發動技能;第二輪中,第 2張卡牌發動技能;
概率爲 0.15,傷害爲5。
2. 第一輪中,第 1張卡牌發動技能;第二輪中,第 3張卡牌發動技能;
概率爲 0.315,傷害爲3。
3. 第一輪中,第 1張卡牌發動技能;第二輪不發動技能;
概率爲 0.035,傷害爲2。
4. 第一輪中,第 2張卡牌發動技能;第二輪中,第 1張卡牌發動技能;
概率爲 0.075,傷害爲5。
5. 第一輪中,第 2張卡牌發動技能;第二輪中,第 3張卡牌發動技能;
概率爲 0.0675,傷害爲4。
6. 第一輪中,第 2張卡牌發動技能;第二輪不發動技能;
概率爲 0.0075,傷害爲3。
7. 第一輪中,第 3張卡牌發動技能;第二輪中,第 1張卡牌發動技能;
概率爲 0.1575,傷害爲3。
8. 第一輪中,第 3張卡牌發動技能;第二輪中,第 2張卡牌發動技能;
概率爲 0.04725,傷害爲4。
9. 第一輪中,第 3張卡牌發動技能;第二輪不發動技能;
概率爲 0.11025,傷害爲1。
10. 第一輪不發動技能;第二輪中,第 1張卡牌發動技能;
概率爲 0.0175,傷害爲2。
11. 第一輪不發動技能;第二輪中,第 2張卡牌發動技能;
概率爲 0.00525,傷害爲3。
12. 第一輪不發動技能;第二輪中,第 3張卡牌發動技能;
概率爲 0.011025,傷害爲1。
13. 第一輪不發動技能;第二輪亦不發動技能;
概率爲 0.001225,傷害爲0。
造成傷害的期望值爲概率與對應傷害乘積之和,爲 3.266025。
對於所有測試數據, 1 <= T <= 444, 1 <= n <= 220, 0 <= r <= 132, 0 < pi < 1, 0 <= di <= 1000。
除非備註中有特殊說明,數據中 pi與di均爲隨機生成。
請注意可能存在的實數精度問題,並採取適當措施。

題解

f[i,j] 表示考慮前i張牌,還有j輪未打出牌的概率。
考慮f[i,j] 它可能是前i-1張牌,還有j輪未打出牌,並且第i張牌在這j輪中均未打出。那麼f[i,j]+=f[i1,j](1pi)j
還有可能是前i-1張牌,還有j+1輪未打出牌,第i張牌在這j+1輪的某一輪被打出。那麼f[i,j]+=f[i1,j+1](1(1pi)j+1) 。在計算概率是順便算一下期望就好了。


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

double f[500][500],p[500],ans;
int n,t,m,d[500]; 

int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        scanf("%lf%d",&p[i],&d[i]);
        memset(f,0,sizeof(f));
        ans=0; f[0][m]=1;
        for(int i=1;i<=n;i++){
            double tmp=1;
            for(int j=0;j<=m;j++){
                f[i][j]+=f[i-1][j]*tmp;
                f[i][j]+=f[i-1][j+1]*(1-tmp*(1-p[i]));
                ans+=f[i-1][j+1]*(1-tmp*(1-p[i]))*d[i];
                tmp*=(1-p[i]);
            }
        }
        printf("%.10lf\n",ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章