【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%

代码

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. #define N 6  
  4. int a[15][15];  
  5. char s[15][15];  
  6. int vis[N][N][N][N][N][N][N][N][N];  
  7. double dp[N][N][N][N][N][N][N][N][N];  
  8.   
  9. inline void init()  
  10. {  
  11.     memset(dp,0,sizeof(dp));  
  12.     memset(vis,0,sizeof(vis));  
  13. }  
  14.   
  15. inline double dfs(int p1,int p2,int p3,int p4,int p5,int p6,int p7,int p8,int p9)  
  16. {  
  17.     if(vis[p1][p2][p3][p4][p5][p6][p7][p8][p9])return dp[p1][p2][p3][p4][p5][p6][p7][p8][p9];  
  18.     vis[p1][p2][p3][p4][p5][p6][p7][p8][p9]=1;  
  19.     int ok=1,tot=0,tmp[10]={0,p1,p2,p3,p4,p5,p6,p7,p8,p9};  
  20.     for(int i=1;i<=9;i++)  
  21.         if(tmp[i]){ok=0;break;}  
  22.     if(ok)return dp[p1][p2][p3][p4][p5][p6][p7][p8][p9]=1.0;  
  23.     double possibility=0.0;  
  24.     for(int i=1;i<=9;i++)  
  25.         for(int j=i+1;j<=9;j++)  
  26.             if(tmp[j]&&tmp[i]&&a[i][tmp[i]]==a[j][tmp[j]])  
  27.             {  
  28.                 tmp[i]--,tmp[j]--;tot++;  
  29.                 possibility+=dfs(tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],tmp[7],tmp[8],tmp[9]);  
  30.                 tmp[i]++,tmp[j]++;  
  31.             }  
  32.     if(tot)dp[p1][p2][p3][p4][p5][p6][p7][p8][p9]=possibility/(1.0*tot);  
  33.     return dp[p1][p2][p3][p4][p5][p6][p7][p8][p9];  
  34. }  
  35.   
  36. int main()  
  37. {  
  38.     while(~scanf("%s%s%s%s",s[1],s[2],s[3],s[4]))  
  39.     {  
  40.         init();  
  41.         for(int j=1;j<=4;j++)a[1][j]=s[j][0]-'0';  
  42.         for(int i=2;i<=9;i++)  
  43.             for(int j=1;j<=4;j++)  
  44.             {  
  45.                 scanf("%s",s[j]);  
  46.                 a[i][j]=s[j][0]-'0';  
  47.             }     
  48.         dfs(4,4,4,4,4,4,4,4,4);  
  49.         printf("%.6lf\n",dp[4][4][4][4][4][4][4][4][4]);  
  50.     }  
  51. }  

猜你喜欢

转载自www.cnblogs.com/NSD-email0820/p/9877503.html