UVA1637Double Patience(概率 + 记忆化搜索)
训练指南P327
题意:36张牌分成9堆, 每堆4张牌。每次拿走某两堆顶部的牌,但需要点数相同。如果出现多种拿法则等概率的随机拿。 如果最后拿完所有的牌则游戏成功,求成功的概率。
开个9维数组表示每一堆的状态,模拟搜索一下
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 const int Max = 6; 7 char s[Max][Max]; 8 int A[10][Max * Max]; 9 int vis[Max][Max][Max][Max][Max][Max][Max][Max][Max]; 10 double d[Max][Max][Max][Max][Max][Max][Max][Max][Max]; 11 double dfs(int s1, int s2, int s3, int s4, int s5, int s6, int s7, int s8, int s9) 12 { 13 if (vis[s1][s2][s3][s4][s5][s6][s7][s8][s9]) 14 return d[s1][s2][s3][s4][s5][s6][s7][s8][s9]; 15 vis[s1][s2][s3][s4][s5][s6][s7][s8][s9] = 1; 16 int T[10] = {0, s1, s2, s3, s4, s5, s6, s7, s8, s9}; 17 bool flag = true; 18 for (int i = 1; i <= 9; i++) 19 { 20 if (T[i]) 21 { 22 flag = false; 23 break; 24 } 25 }//如果全是0,表示结束,这个状态为1 26 if (flag) 27 { 28 return d[s1][s2][s3][s4][s5][s6][s7][s8][s9] = 1.0; 29 } 30 int tot = 0; 31 double cnt = 0; 32 for (int i = 1; i <= 9; i++) 33 { 34 for (int j = i + 1; j <= 9; j++) 35 { 36 if (T[i] > 0 && T[j] > 0 && A[i][ T[i] ] == A[j][ T[j] ]) 37 { 38 T[i]--; 39 T[j]--; 40 tot++; // 当前有几种选择方案 41 cnt += dfs(T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]); // 选择 i 堆 和 j 堆之后剩下的全部取光的概率 42 T[i]++; 43 T[j]++; 44 } 45 } 46 } 47 if (tot > 0) 48 d[s1][s2][s3][s4][s5][s6][s7][s8][s9] = cnt / (1.0 * tot); // (1 / tot ) * cnt;当前状态概率 49 return d[s1][s2][s3][s4][s5][s6][s7][s8][s9]; 50 } 51 int main() 52 { 53 while (scanf("%s%s%s%s", s[1], s[2], s[3], s[4]) != EOF) 54 { 55 for (int i = 1; i <= 4; i++) 56 A[1][i] = s[i][0] - '0'; // A[i][j]用于记录第i堆第j个 57 for (int i = 2; i <= 9; i++) 58 { 59 for (int j = 1; j <= 4; j++) 60 { 61 scanf("%s", s[j]); 62 A[i][j] = s[j][0] - '0'; 63 } 64 } 65 memset(vis, 0, sizeof(vis)); 66 memset(d, 0, sizeof(d)); 67 dfs(4, 4, 4, 4, 4, 4, 4, 4, 4); // 所有的堆都是4个开始搜索 68 printf("%.6lf\n", d[4][4][4][4][4][4][4][4][4]); 69 } 70 return 0; 71 }