[BZOJ4318] WJMZBMR打osu! / Easy (期望DP)
阿新 • • 發佈:2018-07-27
splay print double easy c++ math int 我們 con , \(g[i]=0\).
題目鏈接
Solution
Wa,我是真的被期望折服了,感覺這道題拿來練手正好.
DP的難度可做又巧妙...
我們定義:
\(f[i]\) 代表到第 \(i\) 次點擊的時候的最大答案.
\(g[i]\) 代表到第 \(i\) 此點擊的 \(o\) 的期望長度.
然後看轉移:
1.此時為 \(o\) ,那麽我可以直接計算答案。
由於 \((x+1)^2=x^2+2x+1\) ,所以我們得到轉移方程:
\[f[i]=f[i-1]+2*g[i-1]+1\]
同時由於此時 \(o\) 的長度已經增加,所以同時 \(g[i]=g[i-1]+1\).
2.此時為 \(x\),同樣直接統計答案.
\(f[i]=f[i-1]\)
3.此時為 \(?\) ,那麽我們對於以上兩種情況都有 \(0.5\) 的概率.
然後直接轉移:
\[f[i]=0.5*(f[i-1]+2*g[i-1]+1+f[i-1])\]
\[g[i]=0.5*(g[i-1]+1)\]
然後最後面 \(f[n]\) 即為答案
Code
#include<bits/stdc++.h> #define db double using namespace std; const int maxn=300008; db f[maxn],g[maxn]; int n; string ch; int main() { cin>>n; ch='*'; string s; cin>>s; ch+=s; for(int i=1;i<=n;i++) { if(ch[i]=='o') { f[i]=f[i-1]+2*g[i-1]+1; g[i]=g[i-1]+1; } if(ch[i]=='x') { f[i]=f[i-1]; g[i]=0; } if(ch[i]=='?') { f[i]=0.5*(f[i-1]+2*g[i-1]+1+f[i-1]); g[i]=0.5*(g[i-1]+1); } } printf("%.4lf",f[n]); }
[BZOJ4318] WJMZBMR打osu! / Easy (期望DP)