题意:36张扑克,平分成9摞,两张数字一样的可以拿走,每次随机拿两张,问能拿光的概率。
思路:
直接用搜索,表示出每摞剩余的牌数,然后利用全概率公式即可(P(A) = p(A|b1)*p(b1)+.....+p(A|bn)*p(bn))
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <algorithm> typedef long long ll; using namespace std; int p[10]; int num[9][5]; double dp[5][5][5][5][5][5][5][5][5]; //不同状态时的概率 int vis[5][5][5][5][5][5][5][5][5]; //是否已经搜过 char t1[4],t2[4],t3[4],t4[4]; double dfs(int x1,int x2,int x3,int x4,int x5,int x6,int x7,int x8,int x9) { if(vis[x1][x2][x3][x4][x5][x6][x7][x8][x9]) return dp[x1][x2][x3][x4][x5][x6][x7][x8][x9]; vis[x1][x2][x3][x4][x5][x6][x7][x8][x9] = 1; int top[10] = {x1,x2,x3,x4,x5,x6,x7,x8,x9}; int flag = 0; for(int i = 0; i < 9; i++) //判断是否已经取完 { if(top[i]) { flag = 1; break; } } if(!flag ) return dp[x1][x2][x3][x4][x5][x6][x7][x8][x9] = 1.0; int pnum = 0; double sum = 0.0; //当前情况往下取成功的概率 for(int i = 0; i < 9; i ++) { for(int j = i+1; j < 9 && top[i] != 0; j++) { if(num[i][top[i]] == num[j][top[j]]) { top[i]--; top[j]--; pnum++; //当前情况下有多少种取法 sum += dfs(top[0],top[1],top[2],top[3],top[4],top[5],top[6],top[7],top[8]); top[i]++; top[j]++; } } } if(sum > 0) dp[x1][x2][x3][x4][x5][x6][x7][x8][x9] =(sum/(1.0*pnum)); return dp[x1][x2][x3][x4][x5][x6][x7][x8][x9]; } int main() { while(scanf("%s%s%s%s",t1,t2,t3,t4) != EOF) { num[0][1] = t1[0]; num[0][2] = t2[0]; num[0][3] = t3[0]; num[0][4] = t4[0]; for(int i = 1; i< 9; i++) { scanf("%s%s%s%s",t1,t2,t3,t4); num[i][1] = t1[0]; num[i][2] = t2[0]; num[i][3] = t3[0]; num[i][4] = t4[0]; } memset(vis,0,sizeof(vis)); memset(dp,0,sizeof(dp)); dfs(4,4,4,4,4,4,4,4,4); printf("%.6lf ",dp[4][4][4][4][4][4][4][4][4]); } return 0; }