题意:36张牌分成9堆,每堆四张牌。每次可以拿走某两堆顶部的牌,但需要点数相同。如果有多种拿法则等概率的随机拿。例如9堆顶部的牌分别为KS,KH,KD,9H,8S,8D,7C,7D,6H,则有五种拿法(KS,KH),(KS,KD),(KH,KD),(8S,8D),(7C,7D),每种拿法的概率均为1/5,。如果最后拿完所有牌则游戏成功。按顺序给出每堆牌的四张牌,求成功概率。
思路:记忆化搜索,学习了一种很棒的写法参考
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define mod 1000000007;
using namespace std;
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
const int maxn = 20 + 2;
char card[10][5][3];
map<vector<int>,double> d;
bool init()
{
for(int i = 0; i < 9; i++)
{
for(int j = 0; j < 4; j++)
if(scanf("%s",card[i][j]) != 1) return false;
}
return true;
}
double dfs(int res,vector<int> & num)
{
if(!res) return 1;
if(d.count(num) != 0) return d[num];
double sum = 0,tot = 0;
for(int i = 0;i < 9;i++)
{
if(num[i] == 0) continue;
char c = card[i][num[i] - 1][0];
for(int j = i + 1;j < 9;j++)
{
if(num[j] == 0) continue;
if(c == card[j][num[j] - 1][0])
{
tot++,num[i]--,num[j]--;
sum += dfs(res - 1,num);
num[i]++,num[j]++;
}
}
}
if(!tot) return d[num] = 0;
else return d[num] = sum / tot;
}
int main()
{
while(init())
{
d.clear();
vector<int> num(9,4);
printf("%.6f\n",dfs(18,num));
}
return 0;
}