題意:36張牌分成9堆,每堆4張牌。每次可以拿走某兩堆頂部的牌,但需要點數相同。如果有多種拿法則等概率的隨機拿。例如,9堆頂部的牌分別爲KS,KH,KD,9H, 8S,8D,7C,7D,6H,則有5種拿法(KS,KH),(KS,KD),(KH,KD),(8S,8D),(7C,7D),每種拿法的概率均爲1/5.如果最後拿完所有的牌則遊戲成功。按順序給出每堆牌的4張牌,求成功的概率。
思路:用9元組表示當前的狀態,即每堆的剩餘牌數,dp[][][][][][][][][]表示可以這麼那,則爲1,概率爲 (dp和)/個數。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
const int maxn = 5;
double dp[maxn][maxn][maxn][maxn][maxn][maxn][maxn][maxn][maxn];
int top[10];
bool vis[maxn][maxn][maxn][maxn][maxn][maxn][maxn][maxn][maxn];
vector<char> v[10];
double dfs(int t1, int t2, int t3, int t4, int t5, int t6, int t7, int t8, int t9) {
bool &vvis = vis[t1][t2][t3][t4][t5][t6][t7][t8][t9];
double &x = dp[t1][t2][t3][t4][t5][t6][t7][t8][t9];
if(vvis) return x;
vvis = true;
int top[10] = {t1,t2,t3,t4,t5,t6,t7,t8,t9};
bool flag = false;
for(int i = 0; i < 9; ++i) {
if(top[i]) flag = true;
}
if(!flag) return x = 1.0;
int Count = 0;
for(int i = 0; i < 8; ++i) {
if(top[i])
for(int j = i+1; j < 9; ++j) {
if(top[j] && v[i][top[i]-1] == v[j][top[j]-1]) {
Count++;
top[i]--; top[j]--;
x += dfs(top[0], top[1], top[2], top[3], top[4], top[5], top[6], top[7], top[8]);
top[i]++; top[j]++;
}
}
}
if(x == 0) return x = 0;
else return x = x*1.0/(Count*1.0);
}
int main() {
char s0[2], s1[2], s2[2], s3[2];
while(~scanf("%s%s%s%s", s0, s1, s2, s3)) {
v[0].push_back(s0[0]);
v[0].push_back(s1[0]);
v[0].push_back(s2[0]);
v[0].push_back(s3[0]);
for(int i = 1; i < 9; ++i) {
scanf("%s%s%s%s", s0, s1, s2, s3);
v[i].push_back(s0[0]);
v[i].push_back(s1[0]);
v[i].push_back(s2[0]);
v[i].push_back(s3[0]);
}
printf("%.6lf\n", dfs(4,4,4,4,4,4,4,4,4));
memset(dp, 0, sizeof(dp));
memset(vis, false, sizeof(vis));
for(int i = 0; i < 9; ++i) v[i].clear();
}
}