Problem 1056 : Ben Toh
Problem 1056 : Ben Toh
http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=1056&lang=jp
- 問題概要
今年のUAPCの問題です。
コンテスト中に解くことができてすごくうれしかったです。
最初の日はかならず弁当をゲットできる。
その日弁当をゲットすると、次の日はその半分の確率でゲットできる。
失敗すると、もとの確率にリセットされる。
n日目の期待値を求めよ。
- 解法
DP
dp[i]について、ゲットできず、リセットされたとこから、誤差の許されるところまで減っていく確率を足していく。リセットされる確率 * どんどん減っていく確率をして足していく。つまり、前の取れる確率×0.5^日数*リセットされる確率。iのゲットできない確率からi+1からの、iの日にゲットできなかった場合のものを算出する。
うー、せつめいするのがむずかしい。図でもないととても説明できそうにない。
ソースを見せるのが一番わかり易い。
base リセットされる確率。
rate 1、0.5、0,25と減っていく、問題で定義された確率
prate 前の弁当とれる確率。
nrate j-i日たったときの確率。
つまり、確率 = (前日が1としたときのこの日取れる確率)*(前日の確率)*(リセットして計算し始めたときの確率)
これでdpします。
- ソース
#include<vector> #include<map> #include<queue> #include<stack> #include<cstdio> using namespace std; double dp[100000+1]; main(){ int n; while( cin >> n ) { if(n == 0)break; double ans = 0; fill(dp, dp +n+1, 0); for(int i=0; i<=n; i++){ double rate = 1, prate=1, base=1 - dp[i]; for(int j=i+1; j<=n; j++){ double nrate = rate * prate; if(nrate < 0.0000000001)break; dp[j] += (nrate * base); prate = nrate; rate *= 0.5; } ans += dp[i]; } printf("%0.8lf\n",ans); } }
こういう問題大好き。