单人纸牌_NOI导刊2011提高(04)

题目描述

单人纸牌游戏,共36张牌分成9叠,每叠4张牌面向上。每次,游戏者可以从某两个不同的牌堆最顶上取出两张牌面相同的牌(如黑桃10和梅花10)并且一起拿走。如果最后所有纸牌都被取走,则游戏者就赢了,否则游戏者就输了。 

    George很热衷于玩这个游戏,但是一旦有时有多种选择的方法,George就不知道取哪一种好了,George会从中随机地选择一种走,例如:顶上的9张牌为KS,KH,KD,9H,8S,8D,7C,7D,6H,显然有5种取法:(KS,KH),(KS,KD),(KH,KD),(8S,8D),(7C,7D),当然George取到每一种取法的概率都是1/5。 

    有一次,George的朋友Andrew告诉他,这样做是很愚蠢的,不过George不相信,他认为如此玩最后成功的概率是非常大的。请写一个程序帮助George证明他的结论:计算按照他的策略,最后胜利的概率。 【输入数据】 

    9行,每行4组用空格分开的字串,每个字串两个字符,分别表示牌面和花色,按照从堆底到堆顶的顺序给出。

输入输出格式

输入格式:

  9行,每行4组用空格分开的字串,每个字串两个字符,分别表示牌面和花色,按照从堆底到堆顶的顺序给出。

输出格式:

一行,最后胜利的概率,精确到小数点后6位。

输入输出样例

输入样例#1:
AS 9S 6C KS 
JC QH AC KH 
7S QD JD KD 
QS TS JS 9H 
6D TD AD 8S 
QC TH KC 8D 
8C 9D TC 7C 
9C 7H JH 7D 
8H 6S AH 6H 
输出样例#1:
0.589314
概率dp.
f[][][][][][][][][]表示当前状态(每一堆的牌数)的概率
从f[0][0][0][0][0][0][0][0][0]=1开始,
每次在当前状态枚举往上放哪两张牌,方法数为cnt,当前概率为p
则把所有放上两张牌的状态f+=p/cnt;
为了方便,此处用数组循环。
由于状态太多,此处不好列出转移方程,请看代码。
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 using namespace std;
 6 int x,y,cnt,i[11];
 7 double f[5][5][5][5][5][5][5][5][5];
 8 char a[1001][10];
 9 int main()
10 {
11     for (x=1;x<=9;x++)
12     {
13         char s[15];
14         gets(s+1);
15         a[x][1]=s[10];
16         a[x][2]=s[7];
17         a[x][3]=s[4];
18         a[x][4]=s[1];
19     }
20 f[0][0][0][0][0][0][0][0][0]=1;
21       for (i[1]=0;i[1]<=4;i[1]++)
22       {
23           for (i[2]=0;i[2]<=4;i[2]++)
24           {
25               for (i[3]=0;i[3]<=4;i[3]++)
26               {
27                   for (i[4]=0;i[4]<=4;i[4]++)
28                   {
29                       for (i[5]=0;i[5]<=4;i[5]++)
30                       {
31                           for (i[6]=0;i[6]<=4;i[6]++)
32                           {
33                               for (i[7]=0;i[7]<=4;i[7]++)
34                               {
35                                   for (i[8]=0;i[8]<=4;i[8]++)
36                                   {
37                                       for (i[9]=0;i[9]<=4;i[9]++)
38             if (f[i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]][i[8]][i[9]])
39                                       {double p=f[i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]][i[8]][i[9]];
40                                       cnt=0;
41                                           for (x=1;x<9;x++)
42                                            for (y=x+1;y<=9;y++)
43                                             if (i[x]+1<=4&&i[y]+1<=4&&a[x][i[x]+1]==a[y][i[y]+1])
44                                              cnt++;
45                                         if (cnt>0) 
46                                           for (x=1;x<9;x++)
47                                            for (y=x+1;y<=9;y++)
48                                             if (i[x]+1<=4&&i[y]+1<=4&&a[x][i[x]+1]==a[y][i[y]+1]) 
49                                             {
50                                                 i[x]++;i[y]++;
51            f[i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]][i[8]][i[9]]+=p/(double)(cnt*1.0);
52                                                 i[x]--;i[y]--;
53                                             } 
54                                     }
55                                 }
56                             }
57                         }
58                     }
59                 }
60             }
61         }
62       }
63     printf("%.6lf",f[4][4][4][4][4][4][4][4][4]);
64 }

 

posted @ 2017-06-21 21:21  Z-Y-Y-S  阅读(506)  评论(0编辑  收藏  举报