Code Jam 2008 APAC local onsites Problem C. Millionaire —— 概率DP
题意:
你有X元钱,进行M轮赌博游戏。每一轮可以将所持的任意一部分钱作为赌注(赌注为0元表示这一轮不押),赌注可以是小数的,不是一定要整数。每一轮 赢的概率为P,赢了赌注翻倍,输了赌注就没了。如果你最后持有至少1000000元钱的话,就可以把钱全部带走。要求计算在采取最优策略时,获得至少 1000000元钱的概率。
数据范围:
0<=P<=1
1<=X<=1000000
1<=M<=15
1 int M , X ; 2 double P; 3 double dp[2][(1 << 15) + 1]; 4 void solve() 5 { 6 int n = 1 << M; 7 double *pre = dp[0] , *nxt = dp[1]; 8 memset(pre , 0 , sizeof(double) * (n + 1)); 9 /// memset(pre , 0 , sizeof(pre)); 这样初始化是不行的,因为pre为一个double型的指针,不是整个数组。 10 pre[n] = 1.0; 11 for(int r = 0 ; r < M; r++)///枚举第几轮 12 { 13 for(int i = 0 ; i <= n ; i++)///枚举当前是哪种状态 14 { 15 int step = min(i , n - i);///如果step大于n / 2 , 等会儿转移的时候可能会超过n 16 double t = 0.0; 17 for(int j = 0 ; j <= step ; j++)///枚举当前的所有可能走法 18 { 19 t = max(t , P * pre[i + j] + (1 - P) * pre[i - j]);///求出期望的最大值 20 } 21 nxt[i] = t; 22 } 23 swap(pre , nxt);///交换两个数组的值进行滚动 24 } 25 int i = (LL)X * n / 1000000;///找到X对应的是第几块 26 // for(int i = 0 ; i <= n ; i++)cout << '*' << pre[i] << endl; 27 printf("%.6lf\n" , pre[i]); 28 }