单人纸牌_NOI导刊2011提高(04) [题解]

题目链接

解题思路:

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;
}

 

posted @ 2018-10-31 20:41  zxza695  阅读(173)  评论(0编辑  收藏  举报

Contact with me