P1837 单人纸牌_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
九维动归,乱搞即可
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define pipi f[i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]][i[8]][i[9]] 7 using namespace std; 8 double f[5][5][5][5][5][5][5][5][5]; 9 char s[12][6];char h[12]; 10 int i[12]; 11 int main() 12 { 13 for(int k=1;k<=9;k++) 14 { 15 for(int j=4;j>=1;j--)scanf("%s",h),s[k][j]=h[0]; 16 } 17 f[0][0][0][0][0][0][0][0][0]=1.000; 18 int tot=0; 19 for(i[1]=0;i[1]<=4;i[1]++) 20 for(i[2]=0;i[2]<=4;i[2]++) 21 for(i[3]=0;i[3]<=4;i[3]++) 22 for(i[4]=0;i[4]<=4;i[4]++) 23 for(i[5]=0;i[5]<=4;i[5]++) 24 for(i[6]=0;i[6]<=4;i[6]++) 25 for(i[7]=0;i[7]<=4;i[7]++) 26 for(i[8]=0;i[8]<=4;i[8]++) 27 for(i[9]=0;i[9]<=4;i[9]++) 28 { 29 if(!pipi)continue; 30 double c=pipi; 31 tot=0; 32 for(int j=1;j<=8;j++) 33 for(int k=j+1;k<=9;k++) 34 if(i[j]<4 && i[k]<4 && s[j][i[j]+1]==s[k][i[k]+1])tot++; 35 if(!tot)continue; 36 for(int j=1;j<=8;j++) 37 for(int k=j+1;k<=9;k++) 38 if(i[j]<4 && i[k]<4 && s[j][i[j]+1]==s[k][i[k]+1]) 39 { 40 i[j]++;i[k]++; 41 pipi+=(c/tot); 42 i[j]--;i[k]--; 43 } 44 } 45 printf("%.6lf\n",f[4][4][4][4][4][4][4][4][4]); 46 return 0; 47 }