Bob is playing a poker game called GuanDan. The rules are similar to PaoDeKuai and DouDiZhu. Basically, the game is played on two decks of poker with four jokers in total. And there are some specific patterns of hands that you can play. They will be listed below.
Hand | Description | Example(s) | Counter Example(s) | Difficulty |
---|---|---|---|---|
Solo | Any single card | AS (Spade A) | None | 1 |
Pair | Two cards of the same rank | 0D 0C (Diamond 10 and Club 10) | BJ RJ (Jokers of different colors doesn't count as the same rank) | 1 |
Three Pairs | Three pairs with continuous rank | AH AS 2S 2H 3D 3C, QH QH KH KH AH AH | KH KH AH AH 2H 2H | 1 |
Trio | Three cards of the same rank | AH AH AS, 9H 9S 9C | BJ BJ RJ | 1 |
Full House | A composite of a Trio and a Pair | AH AH AS 2S 2H | None | 1 |
Airplane | Two Trios with continuous rank | AH AH AD 2H 2H 2D, KH KH KD AH AH AD | None | 1 |
Straight | Five cards with continuous rank | AH 2S 3H 4C 5H, 0C JD QH KH AS | JD QH KH AS 2S | 1 |
Straight Flush | Five cards with continuous rank and the same suit | AH 2H 3H 4H 5H, 0H JH QH KH AH | QH KH AH 2H 3H | 0 |
Bomb | Four or more cards of the same rank | 5H 5H 5S 5S, 8H 8H 8S 8S 8C 8C 8D 8D | None | 0 |
Your goal is to play your cards as fast as possible and win the game by first playing all of your cards. Therefore, Bob would like to know the least sum of difficulty value if he combine his cards into valid hands optimally.
The first line is an integer of the number of test cases.
For each test case, the first line contains a character denoting the main rank (rank is in {'A', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K'}). The second line contains 54 characters, two characters is a card. Format is the same as descripted in Notation section. Test cases are randomly "drawn" from random shuffled "decks".
For each test case, output the minimum difficulty if you arrange the cards optimally into hands.
2
3
AD3D8H6HKCKS4DJC3H3C9H2C5H9SJD3CKH7CKCAH5H2C4C3SBJAC5S
6
KC0D4HKD6DJCKC2S8HADJD4D9C7SJH3SBJRJ2DQH5H8S9D5S0S2D5C
6
9
Here's one possible solution for sample 1 and sample 2.
Sample 1: 3H is a wildcard.
3H -> 3C
| AC AD AH 5H 5S || 3C 3D 3S JC JD || 9S || **KC KC KH KS** || BJ || 2C 2C 3C 3C 4C 4D || 5H 6H 7C 8H 9H |
KKKK is a bomb, it has difficulty 0. Others each have difficulty 1. Sum is 6.
Sample 2:
| 2D 2S || 4H || 5H 5S || JD JH KC KC KD || BJ || RJ || 8S 9D 0S JC QH || 6D 7S 8H 9C 0D || AD 2D 3S 4D 5C |
No bomb. Sum is 9.
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<ctype.h> #include<math.h> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; } template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; } const int N = 0, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f; int casenum, casei; char V; int O; pair<int, int>w[30]; int ans; int a[15][4];int cnt[17],cntt[17]; int K(char ch) { if (ch == 'A')return 1; else if (ch == '0')return 10; else if (ch == 'J')return 11; else if (ch == 'Q')return 12; else if (ch == 'K')return 13; else return ch - 48; } void DataIsWeak() { if (a[V][2] > 1)while (1);//最多只有1个万能牌 } void check(int val) { int d[4]; MS(d, 0); for (int i = 1; i <= 15; ++i)if (cnt[i] < 4)++d[cnt[i]]; int FullHouse = min(d[3], d[2]); val += FullHouse; d[3] -= FullHouse; d[2] -= FullHouse; val += d[3] + d[2] + d[1]; gmin(ans, val); } //dfs只搜特殊搭配 顺子,2+2+2,3+3这些 void dfs(int p,int val) { if (val >= ans)return; if (p > 27){check(val);return;} int v = w[p].first; if ( v > 13 || cnt[v] == 0) { dfs(p + 1, val); return; } //尝试1,12345;有同花顺肯定考虑同花顺;没有同花顺可以普通的顺子 int nxt = v + 4; if (nxt == 14)nxt = 1; if (v <= 10 && cnt[v] && cnt[v + 1] && cnt[v + 2] && cnt[v + 3] && cnt[nxt]) { --cnt[v]; --cnt[v + 1]; --cnt[v + 2]; --cnt[v + 3]; --cnt[nxt]; int c = w[p].second; if (a[v][c] && a[v + 1][c] && a[v + 2][c] && a[v + 3][c] && a[nxt][c]) { --a[v][c]; --a[v + 1][c]; --a[v + 2][c]; --a[v + 3][c]; --a[nxt][c]; dfs(p + 1,val); ++a[v][c]; ++a[v + 1][c]; ++a[v + 2][c]; ++a[v + 3][c]; ++a[nxt][c]; } else dfs(p + 1, val + 1); ++cnt[v]; ++cnt[v + 1]; ++cnt[v + 2]; ++cnt[v + 3]; ++cnt[nxt]; } //尝试2,2+2+2 nxt = v + 2; if (nxt == 14)nxt = 1; if (v <= 12 && cnt[v] >= 2 && cnt[v + 1] >= 2 && cnt[nxt] >= 2) { cnt[v] -= 2; cnt[v + 1] -= 2; cnt[nxt] -= 2; dfs(p + 1, val + 1); cnt[v] += 2; cnt[v + 1] += 2; cnt[nxt] += 2; } //尝试3,3+3 nxt = v + 1; if (nxt == 14)nxt = 1; if (cnt[v] >= 3 && cnt[nxt] >= 3) { cnt[v] -= 3;cnt[nxt] -= 3; dfs(p + 1, val + 1); cnt[v] += 3;cnt[nxt] += 3; } dfs(p + 1, val); } void solve() { ans = 27; if (a[V][2] == 1)//有特殊牌,数据中特殊牌最多只会有1张 { a[V][2] = 0; --cnt[V]; for (int v = 1; v <= 13; ++v) { for (int c = 0; c < 4; ++c) { ++a[v][c]; ++cnt[v]; w[O] = MP(v,c); dfs(1, 0); --a[v][c]; --cnt[v]; } } ++cnt[14]; w[O] = MP(14, 0); dfs(1, 0); --cnt[14]; ++cnt[15]; w[O] = MP(15, 0); dfs(1, 0); --cnt[15]; a[V][2] = 1; ++cnt[V]; } else dfs(1, 0); printf("%d\n", ans); } int main() { scanf("%d", &casenum); for (int casei = 1; casei <= casenum; ++casei) { MS(a, 0); MS(cnt, 0); O = 0; scanf(" %c", &V); V = K(V); for (int i = 1; i <= 27; ++i) { char v, c; scanf(" %c %c", &v, &c); if (v == 'B'&&c == 'J') { w[i] = MP(14, 0); ++cnt[14]; continue; } if (v == 'R'&&c == 'J') { w[i] = MP(15, 0); ++cnt[15]; continue; } v = K(v); if (c == 'D')c = 0;else if (c == 'S')c = 1;else if (c == 'H')c = 2;else c = 3; w[i] = MP(v, c); ++a[v][c]; ++cnt[v]; if (v == V&&c == 2)O = i; } DataIsWeak(); solve(); } return 0; } /* 【trick&&吐槽】 1,最好不要因为题目说数据随机化就从一上来就考虑错误的程序。这可能将你带入万丈深渊! 2,做题要有智商啊!爆搜怎么剪枝?用智商剪枝! 3,如果想到用智商剪枝,比赛的时候就6题碾压全场了>_< 呜呜呜! 【题意】 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5672 自己看吧= = 【类型】 搜索+贪心 智商题 好题 【分析】 这道题需要智商。 不能一味爆搜。 我们枚举 1,12345+同花顺 2,3+3 3,2+2+2 剩下的牌可以走 1,炸弹 2,3+2 3,3 4,2 5,1 我们发现—— 对于剩下的牌 1,能走炸弹肯定走炸弹。因为它拆了带别人的话,对答案也依然是没有贡献的。 2,有3张的话,先走3+2,走不了3+2的话走3 3,没有3张的话走2和走1 【时间复杂度&&优化】 搜索的时候只搜索作为开始的牌,最多能把我们带入3个分支,看似是27^k的复杂度,实际因为k平均很小,所以复杂度非常小,可以0msAC。 【数据】 input 100 0 KC KC KH KS AC AD AH 5H 5S 3C 3D 3S JC JD 9S BJ 2C 2C 3C 3C 4C 4D 5H 6H 7C 8H 9H outout 6 input 100 7 4C5C6C7C8C 7C7D7S7D BJBJ6C6D6D AH2C3D4S5H 8C8D9D9D0D7H ACAD output 4 input 100 K 4C5C6C7C8C 7C7D7S7D BJBJ6C6D6D AH2C3D4S5H 8C8D9D9D0D0H ACAD output 4 */