有9组牌,一组4张,每次可以从任意两组从拿出最上面的牌,这两张牌必须点数相同,有多种选择每种选择的概率相同,求最后牌全部被拿完的概率。
一个9元组,数量为5^9=1953125,pro[i]表示状态i成功的概率,它等于后继状态的成功概率的平均值.
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef pair<int,int> pii;
typedef unsigned long long ULL;
typedef long long LL;
const int maxn=100005;
string s[10][5];
char p[15]="6789TJQKA";
int u;
double Pro[100000007];
bool vis[100000007];
int mult=17;
int mod=100000007;
double dfs(int* r);
int main()
{
int d[10];
while(cin>>s[1][1])
{
memset(vis,0,sizeof(vis));
for(int j=2;j<=4;j++)
cin>>s[1][j];
for(int i=2;i<=9;i++)
{
for(int j=1;j<=4;j++)
cin>>s[i][j];
}
for(int i=1;i<=9;i++)
d[i]=4;
printf("%.6lf\n",dfs(d));
}
return 0;
}
bool L(int* r)
{
for(int i=1;i<=9;i++)
{
if(r[i]!=0)
return false;
}
return true;
}
int num(int* rr,char c)
{
int y=0;
for(int i=1;i<=9;i++)
{
if(rr[i]>0&&s[i][rr[i]][0]==c)
y++;
}
return y;
}
int mmm(int* e,int* r,char c)
{
int num=0;
int v=0;
for(int i=1;i<=9;i++)
{
if(r[i]>0&&s[i][r[i]][0]==c)
{
num++;
e[v++]=i;
}
}
return num;
}
bool T(int k,int o)
{
int num=0;
for(int i=0;i<o;i++)
{
if((1<<i)&k)
num++;
}
return num==2;
}
int Hash(int* r)
{
int h=0;
for(int i=1;i<=9;i++)
{
h=(h*mult%mod+r[i])%mod;
}
return h;
}
double dfs(int* r)
{
int h=Hash(r);
if(vis[h]==1)
{
return Pro[h];
}
if(L(r))
{
vis[h]=1;
Pro[h]=1;
return 1;
}
vis[h]=1;
Pro[h]=0;
int tot=0;
for(int i=0;i<9;i++)
{
int o=num(r,p[i]);
if(o>=2)
tot+=o*(o-1)/2;
}
if(tot==0)
{
Pro[h]=0;
return Pro[h];
}
int e[10];
int dd[10];
for(int i=0;i<9;i++)
{
int o=mmm(e,r,p[i]);
if(o>=2)
{
for(int k=0;k<(1<<o);k++)
{
if(T(k,o))
{
memcpy(dd,r,sizeof(int)*10);
for(int f=0;f<o;f++)
{
if((1<<f)&k)
dd[e[f]]--;
}
Pro[h]+=dfs(dd);
}
}
}
}
Pro[h]/=tot;
return Pro[h];
}