1 条题解
-
0
题目描述
在德州扑克中,每位玩家会获得两张底牌,同时桌面上会有五张公共牌。玩家需要从这七张牌中选出五张组成最佳牌型。本题要求我们根据给定的七张牌(前五张为公共牌,后两张为底牌),找出对手可能组成的最强五张牌牌型。如果存在多个花色可以组成相同的最强牌型,则用
'*'
表示花色。输出时,牌需要按点数降序排列(A 始终视为最大),若点数相同则按花色顺序排列('*'
排最后),并附上牌型的全大写名称。解题思路
1. 理解牌型优先级
首先,我们需要明确德州扑克中各种牌型的优先级(从高到低):
- 皇家同花顺 (ROYAL FLUSH)
A、K、Q、J、10,同花色。 - 同花顺 (STRAIGHT FLUSH)
五张连续点数且同花色的牌(A 可以作为最大或最小,但不能同时使用)。 - 四条 (FOUR OF A KIND)
四张同点数的牌,剩余一张为任意牌。 - 葫芦 (FULL HOUSE)
三张同点数 + 一对。 - 同花 (FLUSH)
五张同花色的牌,点数不连续。 - 顺子 (STRAIGHT)
五张连续点数的牌,花色不限。 - 三条 (THREE OF A KIND)
三张同点数的牌,剩余两张为任意牌。
2. 对手的可能牌型
对手的牌型由五张公共牌中的任意五张组成(因为对手的底牌未知)。我们需要遍历所有可能的五张牌组合,找出其中最强的牌型。
3. 牌型判断逻辑
对于任意五张牌,我们需要依次判断其是否符合以下牌型(从高到低检查):
- 皇家同花顺:检查是否为 A、K、Q、J、10 且同花色。
- 同花顺:检查是否为连续点数且同花色。
- 四条:检查是否有四张同点数牌。
- 葫芦:检查是否三张同点数 + 一对。
- 同花:检查是否五张同花色。
- 顺子:检查是否五张连续点数。
- 三条:检查是否三张同点数。
4. 处理花色平局
如果存在多个花色可以组成相同的最强牌型(例如,同花顺可以用不同花色组成),则用
'*'
表示花色。5. 输出格式
- 牌按点数降序排列(A 最大,2 最小)。
- 若点数相同,按花色顺序排列(
c < d < h < s < '*'
)。 - 牌型名称用全大写字母表示。
代码实现思路
- 输入处理:读取输入数据,解析每张牌的点数和花色。
- 生成所有可能的五张牌组合:从七张牌中选取五张,计算所有组合。
- 牌型判断:对每个五张牌组合,判断其牌型。
- 选择最强牌型:在所有可能的牌型中,选择最强的。
- 处理平局:如果有多个花色可选,用
'*'
表示。 - 输出结果:按规则排序并输出。
示例分析
输入:
9c As 3h 8d 2s Jh Ah
输出:
As 5* 4* 3h 2s STRAIGHT
解释:
- 公共牌:
9c As 3h 8d 2s
- 底牌:
Jh Ah
- 可能的五张牌组合中,最强的牌型是 顺子 (STRAIGHT),由
As 3h 2s Jh Ah
组成(A 作为最大点数,但这里需要进一步验证逻辑是否正确)。
总结
本题的关键在于:
- 正确判断牌型:从高到低依次检查每种牌型。
- 处理花色平局:用
'*'
表示多个可选花色。 - 排序输出:按点数和花色顺序排列。
通过遍历所有可能的五张牌组合,并比较它们的牌型,我们可以找到对手可能的最强牌型。
代码实现
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define pii pair<int,int> using namespace std; const int RANK_OFFSET = 2; const int SUIT_OFFSET = 1; inline int decode(char c) { if(c == 'c') return 1; if(c == 'd') return 2; if(c == 'h') return 3; if(c == 's') return 4; if('2' <= c && c <= '9') return c - '0'; switch(c) { case 'T': return 10; case 'J': return 11; case 'Q': return 12; case 'K': return 13; case 'A': return 14; default: return 0; } } struct poker { pii a[5]; int v1, v2; bool operator == (const poker& that) const { return v1 == that.v1 && v2 == that.v2; } bool operator < (const poker& that) const { return v1 == that.v1 ? v2 < that.v2 : v1 < that.v1; } }; pii hand[7]; bool vis[15][5]; // [rank][suit], rank 2-14, suit 1-4 // Comparison function for sorting cards bool card_compare(const pii& x, const pii& y) { return x.first != y.first ? x.first > y.first : x.second < y.second; } inline void evaluate_hand(poker& cur) { pii a[5]; memcpy(a, cur.a, sizeof(a)); sort(a, a+5); bool flush = true; for(int i = 1; i < 5; i++) if(a[i].second != a[i-1].second) flush = false; bool straight = false; if(a[0].first + 1 == a[1].first && a[1].first + 1 == a[2].first && a[2].first + 1 == a[3].first && a[3].first + 1 == a[4].first) { straight = true; } else if(a[4].first == 14 && a[0].first == 2 && a[1].first == 3 && a[2].first == 4 && a[3].first == 5) { straight = true; } int counts[15] = {0}; for(int i = 0; i < 5; i++) counts[a[i].first]++; int four = 0, three = 0, pairs = 0; for(int i = 2; i <= 14; i++) { if(counts[i] == 4) four = i; else if(counts[i] == 3) three = i; else if(counts[i] == 2) pairs++; } // Royal Flush if(flush && straight && a[4].first == 14 && a[0].first == 10) { cur.v1 = 7; return; } // Straight Flush if(flush && straight) { cur.v1 = 6; cur.v2 = (a[4].first == 14 && a[3].first == 5) ? 5 : a[4].first; return; } // Four of a Kind if(four) { cur.v1 = 5; int kicker = 0; for(int i = 0; i < 5; i++) if(a[i].first != four) kicker = a[i].first; cur.v2 = four * 20 + kicker; return; } // Full House if(three && pairs >= 1) { cur.v1 = 4; int pair_val = 0; for(int i = 2; i <= 14; i++) if(counts[i] == 2) pair_val = i; cur.v2 = three * 20 + pair_val; return; } // Flush if(flush) { cur.v1 = 3; cur.v2 = 0; for(int i = 4; i >= 0; i--) cur.v2 = cur.v2 * 20 + a[i].first; return; } // Straight if(straight) { cur.v1 = 2; cur.v2 = (a[4].first == 14 && a[3].first == 5) ? 5 : a[4].first; return; } // Three of a Kind if(three) { cur.v1 = 1; int kickers[2] = {0}; int idx = 0; for(int i = 4; i >= 0; i--) if(a[i].first != three && idx < 2) kickers[idx++] = a[i].first; cur.v2 = three * 400 + kickers[0] * 20 + kickers[1]; return; } // Default case (high card) cur.v1 = 0; } void generate_combinations(int start, int pos, int remaining, poker& cur, poker& best_hand) { if(remaining == 0) { evaluate_hand(cur); if(best_hand.v1 < cur.v1 || (best_hand.v1 == cur.v1 && best_hand.v2 < cur.v2)) { best_hand = cur; } return; } for(int i = start; i <= 7 - remaining; i++) { cur.a[pos] = hand[i]; generate_combinations(i+1, pos+1, remaining-1, cur, best_hand); } } void find_best_hand(poker& best_hand) { poker current; generate_combinations(0, 0, 5, current, best_hand); } void output_hand(const poker& p) { pii a[5]; memcpy(a, p.a, sizeof(a)); sort(a, a+5, card_compare); for(int i = 0; i < 5; i++) { printf("%c%c ", "0023456789TJQKA"[a[i].first], "*cdhs"[a[i].second]); } static const char* hand_names[] = { "", "THREE OF A KIND", "STRAIGHT", "FLUSH", "FULL HOUSE", "FOUR OF A KIND", "STRAIGHT FLUSH", "ROYAL FLUSH" }; puts(hand_names[p.v1]); } int main() { int T; scanf("%d", &T); while(T--) { memset(vis, 0, sizeof(vis)); for(int i = 0; i < 7; i++) { char s[3]; scanf("%2s", s); hand[i] = make_pair(decode(s[0]), decode(s[1])); vis[hand[i].first][hand[i].second] = true; } poker best_hand = {{}, -1, -1}; find_best_hand(best_hand); // Check for wildcard possibilities (opponent's possible hands) poker opponent_best = best_hand; for(int r = 2; r <= 14; r++) { for(int s = 1; s <= 4; s++) { if(vis[r][s]) continue; hand[5] = make_pair(r, s); for(int rr = r; rr <= 14; rr++) { for(int ss = 1; ss <= 4; ss++) { if(rr == r && ss <= s) continue; if(vis[rr][ss]) continue; hand[6] = make_pair(rr, ss); poker current_best = {{}, -1, -1}; find_best_hand(current_best); if(opponent_best < current_best) { opponent_best = current_best; } } } } } output_hand(opponent_best); } return 0; }
- 皇家同花顺 (ROYAL FLUSH)
- 1
信息
- ID
- 1025
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者