Double Patience is a single player game played with a standard 36-card deck. The cards are shuffled and laid down on a table in 9 piles of 4 cards each, faces up.
After the cards are laid down, the player makes turns. In a turn he can take top cards of the same rank from any two piles and remove them. If there are several possibilities, the player can choose any one. If all the cards are removed from the table, the player wins the game, if some cards are still on the table and there are no valid moves, the player loses.
George enjoys playing this patience. But when there are several possibilities to remove two cards, he doesn't know which one to choose. George doesn't want to think much, so in such case he just chooses a random pair from among the possible variants and removes it. George chooses among all possible pairs with equal probability.
For example, if the top cards are KS, KH, KD, 9H, 8S, 8D, 7C, 7D, and 6H, he removes any particular pair of (KS, KH), (KS, KD), (KH, KD), (8S, 8D), and (7C, 7D) with the equal probability of 1/5.
Once George's friend Andrew came to see him and noticed that he sometimes doesn't act optimally. George argued, that it is not important - the probability of winning any given patience with his strategy is large enough.
Help George to prove his statement - given the cards on the table in the beginning of the game, find out what is the probability of George winning the game if he acts as described.
The input file contains several test cases, each of them consists of nine lines. Each line contains the description of four cards that form a pile in the beginning of the game, from the bottom card to the top one.
Each card is described with two characters: one for rank, one for suit. Ranks are denoted as `6' for six, `7' for seven, `8' for eight, `9' for nine, `T' for ten, `J' for jack, `Q' for queen, `K' for king, and `A' for ace. Suits are denoted as `S' for spades, `C' for clubs, `D' for diamonds, and `H' for hearts. For example, ``KS" denotes the king of spades.
Card descriptions are separated from each other by one space.
For each test case, output a line with one real number - the probability that George wins the game if he plays randomly. Your answer must be accurate up to 10-6 .
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
0.589314
#include
#include
#include
#include
using namespace std;
// record[i]代表牌堆情况用整数i(第j位为k代表第j个牌堆有k张牌)表示情况下,获胜的概率
double record[2000000];
// flag[i]=count代表record[i]被计算过
int flag[2000000];
int count;
// card[i][j]代表第i个牌堆的第j张牌(从底到顶)的大小
char card[9][4];
double get_result(int x);
int main()
{
string str;
count = 1;
memset(flag, 0, sizeof(flag));
while(getline(cin, str))
{
// 读入牌堆
for(int i = 0; i <= 3; i++)
card[0][i] = str[i*3];
for(int i = 1; i <= 8; i++)
{
getline(cin, str);
for(int j = 0; j <= 3; j++)
card[i][j] = str[j*3];
}
// 建立初始状态
int x = 0;
for(int i = 0; i <= 8; i++)
x = x*5 + 4;
// 计算结果
printf("%.6f\n", get_result(x));
count++;
}
return 0;
}
// 计算record[x]代表牌堆情况用整数x(第j位为k代表第j个牌堆有k张牌)表示情况下,获胜的概率结果
double get_result(int x)
{
if(flag[x] == count)
return record[x];
flag[x] = count;
// 得出牌堆的情况
int now_c[9];
int k = x;
int win_flag = 1;
for(int i = 8; i >= 0; i--)
{
now_c[i] = k % 5;
k = k / 5;
if(now_c[i] != 0)
win_flag = 0;
}
// 如果没有牌,就赢结束
if(win_flag)
{
record[x] = 1;
return record[x];
}
// 查看可以走的步
int m_count = 0;
double r = 0;
for(int i = 0; i <= 7; i++)
{
if(now_c[i] > 0)
{
for(int j = i+1; j <= 8; j++)
{
if(now_c[j] > 0 && card[i][now_c[i]-1] == card[j][now_c[j]-1])
{
m_count++;
// 生成新的局面,计算结果
int k2 = 0;
for(int m = 0; m <= 8; m++)
{
if(m == i || m == j)
k2 = k2*5 + now_c[m]-1;
else
k2 = k2*5 + now_c[m];
}
r += get_result(k2);
}
}
}
}
if(m_count == 0)
record[x] = 0;
else
record[x] = r / (m_count);
return record[x];
}
题目本身不难,不过在数学专题出现了这个题,很快想到表示当前状态可以用一个9位的5进制整数来表示。
比较有意思的是锻炼了一下动态规划和概率。