UVA1637Double Patience(概率 + 记忆化搜索)

时间:2023-12-23 21:53:19

训练指南P327

题意:36张牌分成9堆, 每堆4张牌。每次拿走某两堆顶部的牌,但需要点数相同。如果出现多种拿法则等概率的随机拿。 如果最后拿完所有的牌则游戏成功,求成功的概率。

开个9维数组表示每一堆的状态,模拟搜索一下

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int Max = ;
char s[Max][Max];
int A[][Max * Max];
int vis[Max][Max][Max][Max][Max][Max][Max][Max][Max];
double d[Max][Max][Max][Max][Max][Max][Max][Max][Max];
double dfs(int s1, int s2, int s3, int s4, int s5, int s6, int s7, int s8, int s9)
{
if (vis[s1][s2][s3][s4][s5][s6][s7][s8][s9])
return d[s1][s2][s3][s4][s5][s6][s7][s8][s9];
vis[s1][s2][s3][s4][s5][s6][s7][s8][s9] = ;
int T[] = {, s1, s2, s3, s4, s5, s6, s7, s8, s9};
bool flag = true;
for (int i = ; i <= ; i++)
{
if (T[i])
{
flag = false;
break;
}
}//如果全是0,表示结束,这个状态为1
if (flag)
{
return d[s1][s2][s3][s4][s5][s6][s7][s8][s9] = 1.0;
}
int tot = ;
double cnt = ;
for (int i = ; i <= ; i++)
{
for (int j = i + ; j <= ; j++)
{
if (T[i] > && T[j] > && A[i][ T[i] ] == A[j][ T[j] ])
{
T[i]--;
T[j]--;
tot++; // 当前有几种选择方案
cnt += dfs(T[], T[], T[], T[], T[], T[], T[], T[], T[]); // 选择 i 堆 和 j 堆之后剩下的全部取光的概率
T[i]++;
T[j]++;
}
}
}
if (tot > )
d[s1][s2][s3][s4][s5][s6][s7][s8][s9] = cnt / (1.0 * tot); // (1 / tot ) * cnt;当前状态概率
return d[s1][s2][s3][s4][s5][s6][s7][s8][s9];
}
int main()
{
while (scanf("%s%s%s%s", s[], s[], s[], s[]) != EOF)
{
for (int i = ; i <= ; i++)
A[][i] = s[i][] - ''; // A[i][j]用于记录第i堆第j个
for (int i = ; i <= ; i++)
{
for (int j = ; j <= ; j++)
{
scanf("%s", s[j]);
A[i][j] = s[j][] - '';
}
}
memset(vis, , sizeof(vis));
memset(d, , sizeof(d));
dfs(, , , , , , , , ); // 所有的堆都是4个开始搜索
printf("%.6lf\n", d[][][][][][][][][]);
}
return ;
}