首页 > 代码库 > 1637 - Double Patience(状态转移+求成功概率)

1637 - Double Patience(状态转移+求成功概率)

用九元组表示当前状态,即每队牌剩的张数,状态总数为5^9=1953125.

设d[ i ]表示状态i对应的成功概率,则根据全概率公式,d[ i ]为后继成功概率的平均值,按照动态规划的写法计算即可。

这个动态规划我不会写,帅哥思路真的很清晰很好啊。

但是学会还是很高兴的

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
#define mem(a) memset(a,0,sizeof(a))

vector<char> v[9];
double d[5][5][5][5][5][5][5][5][5];
int vis[5][5][5][5][5][5][5][5][5];
double dp(int t0,int t1,int t2,int t3,int t4,int t5,int t6,int t7,int t8)
{
    double& ans=d[t0][t1][t2][t3][t4][t5][t6][t7][t8];
    if(vis[t0][t1][t2][t3][t4][t5][t6][t7][t8]) return ans;
       vis[t0][t1][t2][t3][t4][t5][t6][t7][t8]=1;
    int te[9]={t0,t1,t2,t3,t4,t5,t6,t7,t8};
    int ok=1;
    for(int i=0;i<9;i++) if(te[i]){ok=0; break;}
    if(ok) return ans=1;
    ans=0;
    int num=0;
    double pum=0;
    for(int i=0;i<9;i++) if(te[i])
        for(int j=i+1;j<9;j++) if(te[j]&&v[i][te[i]-1]==v[j][te[j]-1])
        {
            num++;
            te[i]--; te[j]--;
            pum+=dp(te[0],te[1],te[2],te[3],te[4],te[5],te[6],te[7],te[8]);
            te[i]++; te[j]++;
        }
    if(num==0) return ans=0;
    else return ans = pum/(num*1.0);
}


int main()
{
    char s[5];
    while(scanf("%s",s)!=EOF)
    {
        mem(d);
        mem(vis);
        for(int i=0;i<9;i++)
            v[i].clear();
        v[0].push_back(s[0]);
        for(int i=1;i<=3;i++)
        {
            scanf("%s",s);
            v[0].push_back(s[0]);
        }
        for(int i=1;i<9;i++)
        {
            for(int j=1;j<=4;j++)
            {
                scanf("%s",s);
                v[i].push_back(s[0]);
            }
        }
        printf("%lf\n",dp(4,4,4,4,4,4,4,4,4));
    }
    return 0;
}


定义状态的方法和状态转移的方法都很好,要学习。

方法值得常思考常学习~