解题思路:
9维概率Dp,类似于递推。
如果用填表法,发现根本不好转移。
考虑用刷表法。
f[5][5][5][5][5][5][5][5][5];//每一堆取了x个的概率
每次记录堆顶相等的数量。
这个数量记为base,即我们当前概率需要除的数字。
然后我们找到是哪些相等,顺推一下,推出的状态
需要累加 能推到它的概率。
还得保证只用4个牌。
代码:
#include<bits/stdc++.h> #define ll long long #define R register using namespace std; int a[10][5],b[10]; double f[5][5][5][5][5][5][5][5][5];//每一堆取了x个的概率 string s; int main(){ for(R int i=1;i<=9;i++) { getline(cin,s); a[i][4]=s[0]; a[i][3]=s[3]; a[i][2]=s[6]; a[i][1]=s[9]; } f[0][0][0][0][0][0][0][0][0]=1; for(b[1]=0;b[1]<=4;++b[1])//顺推 for(b[2]=0;b[2]<=4;++b[2]) for(b[3]=0;b[3]<=4;++b[3]) for(b[4]=0;b[4]<=4;++b[4]) for(b[5]=0;b[5]<=4;++b[5]) for(b[6]=0;b[6]<=4;++b[6]) for(b[7]=0;b[7]<=4;++b[7]) for(b[8]=0;b[8]<=4;++b[8]) for(b[9]=0;b[9]<=4;++b[9]) { R int tot=0; for(R int i=1;i<=9;++i) for(R int j=1;j<i;++j) if(a[i][b[i]+1]==a[j][b[j]+1]&&b[i]+1<=4&&b[j]+1<=4) ++tot; for(R int i=1;i<=9;++i) for(R int j=1;j<i;++j) if(a[i][b[i]+1]==a[j][b[j]+1]&&b[i]+1<=4&&b[j]+1<=4) { R double base=f[b[1]][b[2]][b[3]][b[4]][b[5]][b[6]][b[7]][b[8]][b[9]]; ++b[i];++b[j]; f[b[1]][b[2]][b[3]][b[4]][b[5]][b[6]][b[7]][b[8]][b[9]]=f[b[1]][b[2]][b[3]][b[4]][b[5]][b[6]][b[7]][b[8]][b[9]]+(double)base/tot; --b[i];--b[j]; } } printf("%.6lf",f[4][4][4][4][4][4][4][4][4]); return 0; }