Educational DP Contest I - Coins
問題
問題概要
コインがN枚あり、i番目(1-index)のコインの表が出る確率がp[i-1]、裏が出る確率が1-p[i-1]である。
N枚のコインを投げたとき、表の個数が裏の個数を上回る確率を求めよ。
解法
dp[i][j] : i番目(1-index)のコインまで投げたときに
(表の枚数)-(裏の枚数)=j
となる確率。
0≦i≦N、-N≦j≦N
これだとjが負の数になることがあるので調整する。
dp[i][N+1+j] : i番目(1-index)のコインまで投げたときに
(裏の枚数)-(表の枚数)=j
となる確率。
0≦i≦N、1≦N+1+j≦2*N+1
dp[i][N+1+j]=dp[i-1][N+j]*(1-p[i-1])+dp[i-1][N+2+j]*p[i-1]
i=0かつj=0の時はdp[i][N+1+j]=1
i=0かつj≠0の時はdp[i][N+1+j]=0
答えは
i=Nかつj<0の時のdp[i][N+1+j]の総和
ソースコード
signed main() { int N; cin >> N; vector<double>p(N); rep(i, N) { cin >> p[i]; } vector<vector<double>>dp(N + 1, vector<double>(2 * N + 3)); rep(i, N + 1) { for (int j = (-1) * N; j <= N; j++) { if (i == 0) { if (j == 0) { dp[i][N+1+j] = 1; } else { dp[i][N+1+j] = 0; } } else { dp[i][N + 1 + j] = dp[i - 1][N + j] * (1 - p[i - 1]) + dp[i - 1][N + 2 + j] * p[i - 1]; } } } double ans = 0; rep(i, N + 1) { for (int j = (-1) * N; j <= N; j++) { if (i == N && j < 0) { ans += dp[i][N + 1 + j]; } } } cout << fixed << setprecision(20) << ans << endl; }
コメント
dp[i][j] : i枚目のコインまで投げたとき、表がj枚でる確率
にした方が簡単だった。