题目大意:你手中有五张牌,桌上叠着五张牌,你有超能力,可以让任意张手中的牌与桌上的任意张交换,使得交换以后手中与桌上依旧五张牌。问你交换的最好结果为何种牌?

解题思路:又有一些细节不同。规则如下:

1.straight-flush:同花顺,牌面为T(10) - A,这里不论花色是否相同;

2.four-of-a-kind:四条,牌面有4个相同的值;

3.full-house:船牌,牌面有3个相同值,剩下2个也相同值;

4.flush:同花,五张牌的花色相同,不是同花顺;

5.straight:顺子,五张牌的值连续,A可以作为1也可以作为14;

6.three-of-a-kind:三条,牌面有3个相同的值;

7.two-pairs:两对,牌面有2个对子;

8.one-pair:一对,牌面有一个对子,即2个同值;

9.highest-card:大牌,没有以上牌型。

了解规则以后,用子集生成法的增量构造法,枚举所有手中保留的为原手牌的哪一些,取出桌面上的那些牌也确定了。然后就是判断比较麻烦一些。严格遵守规则就好。顺子的判断,我是用了一个数组存手上的牌的值,要注意不越界。

ac代码:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
char hand[5][5], desk[5][5], kind[10][50];
int re, a[5];
struct node{
int value;
int color;
}own[5];
void init()
{
re = 8;
strcpy(kind[0], "straight-flush");
strcpy(kind[1], "four-of-a-kind");
strcpy(kind[2], "full-house");
strcpy(kind[3], "flush");
strcpy(kind[4], "straight");
strcpy(kind[5], "three-of-a-kind");
strcpy(kind[6], "two-pairs");
strcpy(kind[7], "one-pair");
strcpy(kind[8], "highest-card");
}
int tran(char ch)
{
if (ch == 'K')
return 13;
if (ch == 'Q')
return 12;
if (ch == 'J')
return 11;
if (ch == 'T')
return 10;
if (ch == 'A')
return 1;
return ch-'0';
}
void hand_card(int n)
{
for (int i=0; i<n; i++){
own[i].value = tran(hand[ a[i] ][0]);
own[i].color = hand[ a[i] ][1];
}
for (int i=n,j=0; i<5; i++,j++){
own[i].value = tran(desk[j][0]);
own[i].color = desk[j][1];
}
}
bool compare(node a, node b)
{
if (a.value != b.value)
return a.value < b.value;
return a.color < b.color;
}
void best()
{
int three_kind, two_kind, num[14], temp;
memset(num, 0, sizeof(num));
three_kind = two_kind = 0;
sort(own, own+5, compare);
for (int i=0; i<5; i++)
num[own[i].value]++;
if (num[1] && num[10] && num[11] &&
num[12] && num[13])
re = 0;
for (int i=0; i<=13; i++){
if (num[i] == 4 && re > 1)
re = 1;
else if (num[i] == 2)
two_kind++;
else if (num[i] == 3)
three_kind++;
}
if (three_kind && two_kind && re > 2)
re = 2;
if (own[0].color == own[1].color &&
own[1].color == own[2].color &&
own[2].color == own[3].color &&
own[3].color == own[4].color && re > 3)
re = 3;
temp = own[0].value;
if (num[temp%14] && num[(temp+1)%14] && num[(temp+2)%14]
&& num[(temp+3)%14] && num[(temp+4)%14] && re > 4)
re = 4;
if (three_kind && re > 5)
re = 5;
if (two_kind == 2 && re > 6)
re = 6;
if (two_kind && re > 7)
re = 7;
}

void solve(int cur)
{
int minu=0;
hand_card(cur);
best();
if (cur)
minu = a[cur-1] + 1;
for (int i=minu; i<5; i++){
a[cur] = i;
solve(cur+1);
}
}

int main()
{
while (scanf("%s", &hand[0])!=EOF){
init();
for (int i=1; i<5; i++)
scanf("%s", &hand[i]);
for (int i=0; i<5; i++)
scanf("%s", &desk[i]);
printf("Hand: ");
for (int i=0; i<5; i++)
printf("%s ", hand[i]);
solve(0);
printf("Deck: ");
for (int i=0; i<5; i++)
printf("%s ", desk[i]);
printf("Best hand: %s\n", kind[re]);
}
return 0;
}