zoukankan      html  css  js  c++  java
  • 【UVA1637】纸牌游戏

    题意

    36张牌分成9堆,每堆4张牌。每次可以拿走某两堆顶部的牌,但需要点数相同。如果有 多种拿法则等概率的随机拿。例如,9堆顶部的牌分别为KS, KH, KD, 9H, 8S, 8D, 7C, 7D, 6H,则有5种拿法(KS,KH), (KS,KD), (KH,KD), (8S,8D), (7C,7D),每种拿法的概率均为1/5。 如果最后拿完所有牌则游戏成功。按顺序给出每堆牌的4张牌,求成功概率。

    分析

    为啥一张牌是两个字符组成??这什么奇怪的牌??按照题面给的例子就是说,只要第一个字符相同就OK了吧。。

    于是我们考虑预处理存每一堆牌的每一位的花色的状态,然后因为牌的数量很少,开个九维的dp来存状态,用记忆化搜索转移。

    其实转移方法就很简单了,在dfs里枚举相同的两堆堆顶,然后把这两堆顶部的牌取走作为下一个状态,计算一共有多少方案数以及这些方案数成功的概率之和。

    那么本状态成功的概率就是 ∑可达的下一个状态成功概率 ÷ 可达的方案数

    而边界就是全部取光的状态的成功概率为100%

    代码

    #include<bits/stdc++.h>  
    using namespace std;  
    #define N 6  
    int a[15][15];  
    char s[15][15];  
    int vis[N][N][N][N][N][N][N][N][N];  
    double dp[N][N][N][N][N][N][N][N][N];  
      
    inline void init()  
    {  
        memset(dp,0,sizeof(dp));  
        memset(vis,0,sizeof(vis));  
    }  
      
    inline double dfs(int p1,int p2,int p3,int p4,int p5,int p6,int p7,int p8,int p9)  
    {  
        if(vis[p1][p2][p3][p4][p5][p6][p7][p8][p9])return dp[p1][p2][p3][p4][p5][p6][p7][p8][p9];  
        vis[p1][p2][p3][p4][p5][p6][p7][p8][p9]=1;  
        int ok=1,tot=0,tmp[10]={0,p1,p2,p3,p4,p5,p6,p7,p8,p9};  
        for(int i=1;i<=9;i++)  
            if(tmp[i]){ok=0;break;}  
        if(ok)return dp[p1][p2][p3][p4][p5][p6][p7][p8][p9]=1.0;  
        double possibility=0.0;  
        for(int i=1;i<=9;i++)  
            for(int j=i+1;j<=9;j++)  
                if(tmp[j]&&tmp[i]&&a[i][tmp[i]]==a[j][tmp[j]])  
                {  
                    tmp[i]--,tmp[j]--;tot++;  
                    possibility+=dfs(tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],tmp[7],tmp[8],tmp[9]);  
                    tmp[i]++,tmp[j]++;  
                }  
        if(tot)dp[p1][p2][p3][p4][p5][p6][p7][p8][p9]=possibility/(1.0*tot);  
        return dp[p1][p2][p3][p4][p5][p6][p7][p8][p9];  
    }  
      
    int main()  
    {  
        while(~scanf("%s%s%s%s",s[1],s[2],s[3],s[4]))  
        {  
            init();  
            for(int j=1;j<=4;j++)a[1][j]=s[j][0]-'0';  
            for(int i=2;i<=9;i++)  
                for(int j=1;j<=4;j++)  
                {  
                    scanf("%s",s[j]);  
                    a[i][j]=s[j][0]-'0';  
                }     
            dfs(4,4,4,4,4,4,4,4,4);  
            printf("%.6lf
    ",dp[4][4][4][4][4][4][4][4][4]);  
        }  
    }  
  • 相关阅读:
    11
    961. N-Repeated Element in Size 2N Array
    用numpy.pad()对图像进行填充及简单的图像处理
    709. To Lower Case
    929. Unique Email Addresses
    771. Jewels and Stones
    谭凯---访谈录
    如何拍照
    主题阅读法
    社会各职业工作重心和流程
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9877503.html
Copyright © 2011-2022 走看看