标签:
http://acm.split.hdu.edu.cn/showproblem.php?pid=3076
题意:两个人玩游戏,给出各自掷骰子得到不同点数的概率,点数小的扣一血,相同不扣血。
思路:概率DP,处理到第二个人血量剩余1的时候,然后再处理他降到0的时候的情况,不能直接循环第二个人血量为0的情况,即ans += dp[i][0] (1 <= i <= h1),因为这样的话dp[i][0]继承了dp[i+1][0]的状态,但是为0的时候游戏已经停止了,这样是不合理的。应该是ans += dp[i][1] * win / (1 - ave),这样的话才不会错,要注意考虑(1-ave)的情况,因为当前回合如果平局的话,下一个回合还是有机会赢的。(PS:很感谢ZLW师兄帮我debug了这题好久233)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <cmath> 6 using namespace std; 7 const double eps = 0.00000001; 8 double d[2][6]; 9 double dp[2005][2005]; 10 11 int main() 12 { 13 int h1, h2; 14 while(~scanf("%d%d", &h2, &h1)) { //题目输入反了 15 double win = 0, lose = 0, ave = 0; 16 for(int i = 0; i < 2; i++) 17 for(int j = 0; j < 6; j++) 18 scanf("%lf", &d[i][j]); 19 for(int i = 0; i < 6; i++) { 20 for(int j = 0; j < 6; j++) { 21 if(i == j) ave += d[0][i] * d[1][j]; 22 else if(i < j) lose += d[0][i] * d[1][j]; 23 else win += d[0][i] * d[1][j]; 24 } 25 } 26 // printf("SIZE : %d\n", sizeof(dp)); 27 double ans = 0; 28 if(eps >= fabs(1 - ave)) { 29 printf("%.6f\n", ans); 30 continue; 31 } 32 for(int i = 0; i <= h1+1; i++) 33 for(int j = 0; j <= h2+1; j++) 34 dp[i][j] = 0; 35 // dp[h1+1][h2-1] = dp[h1-1][h2+1] = dp[h1+1][h2] = dp[h1][h2+1] = 0; 36 dp[h1][h2] = 1; 37 for(int i = h1; i >= 0; i--) { 38 for(int j = h2; j >= 0; j--) { 39 if(i == h1 && j == h2) continue; 40 dp[i][j] = (dp[i+1][j] * lose + dp[i][j+1] * win) / ((double)1 - ave); 41 } 42 } 43 for(int i = 1; i <= h1; i++) 44 ans += dp[i][1] * win / ((double)1 - ave); 45 printf("%.6f\n", ans); 46 } 47 return 0; 48 }
标签:
原文地址:http://www.cnblogs.com/fightfordream/p/5792163.html