UVa1637

来源:互联网 发布:南京奥派软件 编辑:程序博客网 时间:2024/05/24 01:01

题目链接

简介:
有九堆poker,每堆4张,每次从任意两堆的顶部选两张相同花色的拿走
都拿走就胜利了,问胜利的概率:

分析:
用九元组表示当前状态(每一队还剩下多少张牌)
d[i]表示状态i获胜的概率
由全概率概率公式可以得到,d[i]就等于ta所有后继状态获胜的平均值

tip

当前状态若没有后继状态时,d[i]=0
不然会发生运算溢出

数组清零

//这里写代码片#include<cstdio>#include<cstring>#include<iostream>using namespace std;int poker[10][5];char s[5];bool vis[5][5][5][5][5][5][5][5][5];double f[5][5][5][5][5][5][5][5][5];int n[10];int get(char *s){    switch(s[0])    {        case 'A': return 1;        case 'K': return 13;        case 'J': return 11;        case 'Q': return 12;        case 'T': return 10;        default: return s[0]-'0';    }}int read(){    for (int i=1;i<=9;i++)        for (int j=1;j<=4;j++)        {            if (scanf("%s",&s)!=1) return 0;            poker[i][j]=get(s);        }    return 1;}double dp(int *n,int c){    if (!c) return 1.0;    if (vis[n[1]][n[2]][n[3]][n[4]][n[5]][n[6]][n[7]][n[8]][n[9]])         return f[n[1]][n[2]][n[3]][n[4]][n[5]][n[6]][n[7]][n[8]][n[9]];    vis[n[1]][n[2]][n[3]][n[4]][n[5]][n[6]][n[7]][n[8]][n[9]]=1;    double ans=0;    int tt=0;    for (int i=1;i<=9;i++)        if (n[i])        for (int j=i+1;j<=9;j++)            if (n[j]&&poker[i][n[i]]==poker[j][n[j]])            {                tt++;                n[i]--; n[j]--;                ans+=dp(n,c-2);                n[i]++; n[j]++;            }    if (!tt) ans=0;                  //这种状态下不能成功     else ans/=tt;    f[n[1]][n[2]][n[3]][n[4]][n[5]][n[6]][n[7]][n[8]][n[9]]=ans;    return ans;}int main(){    while (read())    {        memset(vis,0,sizeof(vis));        memset(f,0,sizeof(f));              for (int i=1;i<=9;i++) n[i]=4;          printf("%0.6lf\n",dp(n,36));    }    return 0;}