——by A Code Rabbit
Description
一道蛋疼的题目,堪称模拟题。
玩牌。
你有5张手牌,可以舍弃任意张,然后从桌上抽牌。
这时候,你突然牛逼了,你可以洞察桌上从上到下放的都是什么牌。
好了。
输入你手上的5张牌和桌面最上方的5张牌。
输出你可以拿到的最强的组合。
Types
Brute Force :: Elementary Skills
Analysis
要想A题,还要会玩扑克。
题目的样例已经给出扑克的各种组合的名称,并且从上到下,从强到弱。
这里也大概蛋疼得说明一下——
- straight-flush,5张牌花色相同,点数递增1。
- four-of-a-kind,5张牌有4张牌点数相同。
- full-house,5张牌有3张牌点数相同,而且另外2张点数也相同。
- flush,5张牌花色相同,但是点数没有递增1。
- straight,5张牌点数递增1,但是花色不同。
- three-of-a-kind,5张牌有3张点数相同,另外2张点数不同。
- two-pairs,5张牌有两对牌点数相同。
- one-pair,5张牌有一对牌点数相同。
- highest-card,木有符合上面任何条件。
好了,接下来就是枚举弃牌的各种情况,然后各种蛋疼的判断函数,去判断牌属于什么类型。
枚举的时候,可以利用二进制数位运算。例如,01010
就表示保留第二张和第四张牌,然后从桌上抽3张牌补齐5张。
而判断的时候,可以利用计数的思想——
- 用一个count数组,计算点数出现的次数。
- 再用另一个count数组,计算“点数出现次数”出现的次数……(虽然很绕口,但是你懂的)
这样就方便多了。
Solution
// UVaOJ 131
// The Psychic Poker Player
// by A Code Rabbit
#include <cstdio>
#include <cstring>
#include <map>
using namespace std;
struct Poker {
char value;
char suit;
};
const int NUM_CARD = 5;
const int LIMITS_VALUES = 15;
const char str_write[][20] = {
"highest-card",
"one-pair",
"two-pairs",
"three-of-a-kind",
"straight",
"flush",
"full-house",
"four-of-a-kind",
"straight-flush",
};
enum Type {
HIGHEST_CARD,
ONE_PAIR,
TWO_PAIRS,
THREE_OF_A_KIND,
STRAIGHT,
FLUSH,
FULL_HOUSE,
FOUR_OF_A_KIND,
STRAIGHT_FLUSH,
};
char ch;
map<char, int> int_value;
Poker hand[NUM_CARD];
Poker deck[NUM_CARD];
Type type_max;
int count_value[LIMITS_VALUES];
int count_value_same[NUM_CARD];
bool IsSameSuit(Poker card[]);
bool IsOrder(Poker card[]);
Type JudgeType(Poker card[]);
void Search(int x);
int main() {
// Make map.
int_value['A'] = 1;
for (int i = 2; i < 10; ++i) {
int_value['0' + i] = i;
}
int_value['T'] = 10;
int_value['J'] = 11;
int_value['Q'] = 12;
int_value['K'] = 13;
// Let's start the game!
while (scanf("%c%c%c", &hand[0].value, &hand[0].suit, &ch) != EOF) {
// Inputs.
for (int i = 1; i < NUM_CARD; ++i) {
scanf("%c%c%c", &hand[i].value, &hand[i].suit, &ch);
}
for (int i = 0; i < NUM_CARD; ++i) {
scanf("%c%c%c", &deck[i].value, &deck[i].suit, &ch);
}
// Search.
type_max = HIGHEST_CARD;
for (int i = 0; i < 1 << NUM_CARD; ++i) {
Search(i);
}
// Outputs.
printf("Hand: ");
for (int i = 0; i < NUM_CARD; ++i) {
printf("%c%c ", hand[i].value, hand[i].suit);
}
printf("Deck: ");
for (int i = 0; i < NUM_CARD; ++i) {
printf("%c%c ", deck[i].value, deck[i].suit);
}
printf("Best hand: %s\n", str_write[type_max]);
}
return 0;
}
bool IsSameSuit(Poker card[]) {
for (int i = 1; i < NUM_CARD; ++i) {
if (card[i].suit != card[0].suit) {
return false;
}
}
return true;
}
bool IsOrder(Poker card[]) {
memset(count_value, 0, sizeof(count_value));
for (int i = 0; i < NUM_CARD; ++i) {
++count_value[int_value[card[i].value]];
if (card[i].value == 'A') {
++count_value[14];
}
}
int num = 0;
for (int i = 0; i < LIMITS_VALUES && num < 5; ++i) {
if (count_value[i]) {
++num;
} else {
num = 0;
}
}
if (num == 5) {
return true;
} else {
return false;
}
}
Type JudgeType(Poker card[]) {
memset(count_value, 0, sizeof(count_value));
memset(count_value_same, 0, sizeof(count_value_same));
for (int i = 0; i < NUM_CARD; ++i) {
++count_value[int_value[card[i].value]];
}
for (int i = 1; i <= 13; ++i) {
++count_value_same[count_value[i]];
}
if (IsSameSuit(card) && IsOrder(card)) {
return STRAIGHT_FLUSH;
} else
if (count_value_same[4]) {
return FOUR_OF_A_KIND;
} else
if (count_value_same[3] && count_value_same[2]) {
return FULL_HOUSE;
} else
if (IsSameSuit(card)) {
return FLUSH;
} else
if (IsOrder(card)) {
return STRAIGHT;
} else
if (count_value_same[3]) {
return THREE_OF_A_KIND;
} else
if (count_value_same[2] == 2) {
return TWO_PAIRS;
} else
if (count_value_same[2] == 1) {
return ONE_PAIR;
} else {
return HIGHEST_CARD;
}
}
void Search(int x) {
Poker card[NUM_CARD];
int top = 0;
for (int i = 0; i < NUM_CARD; ++i) {
if (x & (1 << i)) {
card[top++] = hand[i];
}
}
for (int i = 0; i < NUM_CARD && top < 5; ++i) {
card[top++] = deck[i];
}
Type type = JudgeType(card);
type_max = type > type_max ? type : type_max;
}
参考资料:刺客的博客