【ZOJ3921 2016年浙大2月月赛G】【爆搜+智商贪心剪枝 好题】Guan Dan 2副牌取27张最少出光牌次数
来源:互联网 发布:php pack函数 编辑:程序博客网 时间:2024/06/06 04:31
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.
Notation
- A card contains two characters
- The first character is its rank, the second character is its suit
- For an ordinary card, rank can be A, 2, 3, 4, 5, 6, 7, 8, 9, 0, J, Q, K (A for Ace, 0 for 10)
- J, Q, K can be taken as 11, 12, 13 respectively. Ace can be taken as either 1 or 14.
- Suit can be D, S, H, C (Diamond, Spade, Heart, Club)
- So there are 13 * 4 = 52 different ordinary cards
- Special cards: BJ, RJ (BJ for Black Joker, RJ for Red Joker)
- So all cards are [A-K][DSHC]*2 + BJ*2 + RJ*2, in total 108 cards.
Hands you can play
Clarification
- Jokers' rank is not continuous with ordinary cards
- RJs have the same rank, BJs have the same rank, but an RJ and a BJ do not have the same rank.
- Ranks being continuous means they form a sequence of natural numbers such that each number is 1 plus the number before it
Special rules
- There is a main rank for each game. It can only be one of A, 2, 3, ..., K.
- The two cards of the main rank with a Heart suit are wildcards.
- A wildcard can be used as any card except the jokers.
Goal
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.
Input
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".
Output
For each test case, output the minimum difficulty if you arrange the cards optimally into hands.
Sample Input
23AD3D8H6HKCKS4DJC3H3C9H2C5H9SJD3CKH7CKCAH5H2C4C3SBJAC5S6KC0D4HKD6DJCKC2S8HADJD4D9C7SJH3SBJRJ2DQH5H8S9D5S0S2D5C
Sample Output
69
Hint
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|1typedef 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+2nxt = 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+3nxt = 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+33,2+2+2剩下的牌可以走1,炸弹2,3+23,34,25,1我们发现——对于剩下的牌1,能走炸弹肯定走炸弹。因为它拆了带别人的话,对答案也依然是没有贡献的。2,有3张的话,先走3+2,走不了3+2的话走33,没有3张的话走2和走1【时间复杂度&&优化】搜索的时候只搜索作为开始的牌,最多能把我们带入3个分支,看似是27^k的复杂度,实际因为k平均很小,所以复杂度非常小,可以0msAC。【数据】input1000KC KC KH KSAC AD AH 5H 5S3C 3D 3S JC JD9SBJ2C 2C 3C 3C 4C 4D5H 6H 7C 8H 9Houtout6input10074C5C6C7C8C7C7D7S7DBJBJ6C6D6DAH2C3D4S5H8C8D9D9D0D7HACADoutput4input100K4C5C6C7C8C7C7D7S7DBJBJ6C6D6DAH2C3D4S5H8C8D9D9D0D0HACADoutput4*/
- 【ZOJ3921 2016年浙大2月月赛G】【爆搜+智商贪心剪枝 好题】Guan Dan 2副牌取27张最少出光牌次数
- 【ZOJ3921 2016年浙大2月月赛L】【随机化 答案猜解】Parity Modulo P 大数mod大数mod2
- 【ZOJ3921 2016年浙大2月月赛I】【物理题 底乘高积分式思维】In the Rain 圆柱体人行走 吸收雨体积
- 【ZOJ3916 2016年浙大2月月赛B】【贪心 STL-SET】Buy Cakes n蛋糕k张折扣券蛋糕双价最多能买蛋糕数
- 【ZOJ3921 2016年浙大2月月赛J】【题目观察 暴力 大组合数】Musical Notes n个数,数值为1 2 4 8 16,和恰为m方案数
- 【ZOJ3919 2016年浙大2月月赛E】【简单计算几何 贪心】Ellipse 椭圆内切圆外切平行四边形最大最小面积
- 浙大 4月月赛
- NEU 2016年2月月赛总结
- 浙大2014 3月月赛I题(伸展树)
- 【Codeforces Round 323 (Div 2)B】【贪心】Robot's Task 最少转弯次数拿走所有物品
- ZOJ-3964 2017年浙大省赛G题博弈
- 中南大学2012年8月月赛 H题 Happy watering 贪心算法
- 【洛谷2017年3月月赛】Round1第四题-环套树森林DFS+贪心
- POJ2431贪心(最少加油次数)
- usaco 2017 2月月赛
- Zoj 3647 Gao the Grid ( 2012年浙大9月月赛)组合数学
- 【HDU5740 2016 Multi-University Training Contest 2G】【二分图染色+费用流+路径输出】Glorious Brilliance 最少交换次数使得相邻点颜色
- 2012年7月2日 题:使用最少张数的人民币纸币,凑成上述的钱数m
- masonry约束的小细节
- 微信支付(掃碼支付),開發日誌
- smb 安装
- 安装设备 PrimeSense 1.09_openni2
- hdu1269(邻接表+dfs)
- 【ZOJ3921 2016年浙大2月月赛G】【爆搜+智商贪心剪枝 好题】Guan Dan 2副牌取27张最少出光牌次数
- 面向对象的六大原则之 —— 接口隔离原则
- Android开发技巧——Camera拍照功能
- android 深入浅出 群内“每日一问” 问答总结
- .getClass()、.class、.forName()
- Tomcat version 7.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 Web
- Java利用ImageMagick调用linux系统命令实现Ai或者PSD文件转化为jpg或者png文件
- 虚拟机克隆后eth0网卡变成eth2网卡并且IP地址消失问题解决
- 从Bootstrap中分离出tab组件的样式