●BZOJ 4008 [HNOI2015]亞瑟王
阿新 • • 發佈:2018-03-11
同時 sca lin esp tar log 第一次 pow main
上式表示重新編號後的在第1輪發動技能的概率+在第2輪發動技能的概率+……+在第R-j輪發動技能的概率。
然而不需要這麽麻煩的計算,因為上面的g=1-(1-p)^(R-j),(自己YY為什麽是對的吧)
然後把對f[i+1]進行貢獻:f[i+1]+=dp[i][j]*g
題鏈:
http://www.lydsy.com/JudgeOnline/problem.php?id=4008
題解:
概率dp,神仙題
如果我們可以求出每種牌被取到的概率f,那麽最後期望造成的傷害也就很好計算了。
定義dp[i][j]表示有j輪遊戲在1~i中的某張牌處就結束的概率。
那麽此時我們考慮dp[i][j]會怎樣對f[i+1]造成貢獻:
只剩下了R-j輪遊戲進行到了第i+1張牌,怎麽計算這種情況下第i+1張牌發動技能的概率g呢?
(令p為其發動技能的概率,並給這R-j輪遊戲重新依次編號為1,2,……,R-j)
顯然有:g=p+(1-p)*p+(1-p)^2*p+p……+(1-p)^(R-j-1)*p
上式表示重新編號後的在第1輪發動技能的概率+在第2輪發動技能的概率+……+在第R-j輪發動技能的概率。
然而不需要這麽麻煩的計算,因為上面的g=1-(1-p)^(R-j),(自己YY為什麽是對的吧)
然後把對f[i+1]進行貢獻:f[i+1]+=dp[i][j]*g
接下來考慮如何轉移dp[i][j]:
1.這R-j輪可以進行到第i+1張牌的機會都沒有讓其發動技能:
dp[i+1][j]+=dp[i][j]*(1-p)^(R-j)
2.這R-j輪可以進行到第i+1張牌的機會讓其發動了一次技能:
dp[i+1][j+1]+=dp[i][j]*(1-(1-p)^(R-j))
然後就是不斷轉移dp的同時去求出f[]數組。
(真的是神仙題,題解都看了好久,好像第一次遇到這種定義了一個莫名其妙的dp狀態去輔助求出另外一個東西從而得出答案的題。。。)
代碼:
#include<bits/stdc++.h> using namespace std; double dp[250][150],p[250],f[250],ans; int d[250]; int N,R,Case; double fastpow(double a,int b){ double ret=1; for(;b;a=a*a,b>>=1) if(b&1) ret*=a; return ret; } int main(){ for(scanf("%d",&Case);Case;Case--){ scanf("%d%d",&N,&R); for(int i=1;i<=N;i++) scanf("%lf%d",&p[i],&d[i]),f[i]=0; for(int i=0;i<=N;i++) for(int j=0;j<=R;j++) dp[i][j]=0; dp[0][0]=1; ans=0; for(int i=0;i<N;i++) for(int j=0;j<=R;j++){ double k=fastpow(1-p[i+1],R-j); dp[i+1][j]+=dp[i][j]*k; if(j+1<=R){ dp[i+1][j+1]+=dp[i][j]*(1-k); f[i+1]+=dp[i][j]*(1-k); } } for(int i=1;i<=N;i++) ans+=f[i]*d[i]; printf("%.10lf\n",ans); } return 0; }
●BZOJ 4008 [HNOI2015]亞瑟王