0232:Life Game
問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0232
動的計画法で解いた。
dp[マスの番号][所持金]:=マス i に所持金 j で行ける確率
とすると、
人生ゲームにイベントマスがなければ
dp[i + v[k] ][j] += dp[i][j]/x
v[k]はルーレットの数字。xはルーレットの数字の個数。
イベントを考えると、
イベント1 aだけ進む
dp[ i + v[k] + a ][j] += dp[i][j]/x
イベント2 お金a円をゲット
dp[ i + v[k] ][ j + a ] += dp[i][j]/x
イベント3 お金a円を失くした
dp[ i + v[k] ][ j - a ] += dp[i][j]/x
#include<iostream> #include<algorithm> #include<vector> #include<map> using namespace std; struct M{int e,a;}; int main(void){ int x,y,z,n; double dp[51][5001]; M in; map<int,M>m; while(cin >> x >> y >> z,x|y|z){ vector<int>v(x); m.clear(); for(int i=0;i<x;i++)cin >> v[i]; for(int i=0;i<z;i++){ cin >> n >> in.e >> in.a; m[n]=in; } fill(dp[0],dp[51],0); dp[0][0]=1; for(int i=0;i<y;i++){ for(int j=0;j<5001;j++){ for(int k=0;k<x;k++){ int nx=i+v[k]; if(m[nx].e==1)dp[min(y,nx+m[nx].a)][j]+=dp[i][j]/x; else if(m[nx].e==2)dp[nx][j+m[nx].a]+=dp[i][j]/x; else if(m[nx].e==3)dp[nx][max(0,j-m[nx].a)]+=dp[i][j]/x; else dp[min(y,nx)][j]+=dp[i][j]/x; } } } double ans=0; for(int j=0;j<5001;j++)ans+=dp[y][j]*j; cout << (int)ans << endl; } return 0; }