P2668 斗地主

题目描述

牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中, 牌的大小关系根据牌的数码表示如 下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小 王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取 得游戏的胜利。

现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。

需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。

具体规则如下:

本题数据随机,不支持hack,要hack或强力数据请点击这里

输入输出格式

输入格式:

第一行包含用空格隔开的2个正整数T和n,表示手牌的组数以及每组手牌的张数。

接下来T组数据,每组数据n行,每行一个非负整数对aibi表示一张牌,其中ai示牌的数码,bi表示牌的花色,中间用空格隔开。特别的,我们用1
来表示数码A,11表示数码J,12表示数码Q,13表示数码K;黑桃、红心、梅花、方片分别用1-4来表示;小王的表示方法为01,大王的表示方法为
02。

输出格式:

共T行,每行一个整数,表示打光第i手牌的最少次数。

输入输出样例

输入样例#1:

  1. 1 8
  2. 7 4
  3. 8 4
  4. 9 1
  5. 10 4
  6. 11 1
  7. 5 1
  8. 1 4
  9. 1 1
输出样例#1:

  1. 3
输入样例#2:

  1. 1 17
  2. 12 3
  3. 4 3
  4. 2 3
  5. 5 4
  6. 10 2
  7. 3 3
  8. 12 2
  9. 0 1
  10. 1 3
  11. 10 1
  12. 6 2
  13. 12 1
  14. 11 3
  15. 5 2
  16. 12 4
  17. 2 2
  18. 7 2
输出样例#2:

  1. 6

说明

样例1说明

共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张牌(黑桃5)以及对子牌(黑桃A以及方片A)在3次内打光。

对于不同的测试点, 我们约定手牌组数T与张数n的规模如下:

数据保证:所有的手牌都是随机生成的。

95分。。。卡到极限了,尽力了

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <queue>
  7. #define min(a, b) ((a) < (b) ? (a) : (b))
  8. #define max(a, b) ((a) > (b) ? (a) : (b))
  9.  
  10. inline void swap(int &x, int &y)
  11. {
  12. long long tmp = x;x = y;y = tmp;
  13. }
  14.  
  15. inline void read(int &x)
  16. {
  17. x = ;char ch = getchar(), c = ch;
  18. while(ch < '' || ch > '')c = ch, ch = getchar();
  19. while(ch <= '' && ch >= '')x = x * + ch - '', ch = getchar();
  20. if(c == '-')x = -x;
  21. }
  22.  
  23. const int INF = 0x3f3f3f3f;
  24.  
  25. int t, n, cnt[], tmp, ans, tmp2, tmp3, tmp4;
  26. char s[];
  27.  
  28. //当前正在打第step步, 剩余now个
  29. void dfs(int step, int now)
  30. {
  31. ans = min(ans, step - + now);
  32. if(step > ans)return;
  33. //枚举三顺子
  34. if(tmp3 > && now >= )
  35. {
  36. for(register int i = ;i <= ;++ i)
  37. {
  38. if(cnt[i] > && cnt[i + ] >= )
  39. {
  40. cnt[i] -= , cnt[i + ] -= ;
  41. tmp3 -= ;tmp2 -= ;
  42. dfs(step + , now - );
  43. register int j = i + ;
  44. int t = ;
  45. for(;j <= ;++ j)
  46. {
  47. if(tmp3 < )break;
  48. if(cnt[j] > ) cnt[j] -= , ++ t, tmp3 -= , tmp2 -= , dfs(step + , now - (j - i + ) * );
  49. else break;
  50. }
  51. -- j;
  52. for(;j >= i + ;-- j) cnt[j] += ;
  53. cnt[i] += , cnt[i + ] += ;
  54. tmp3 += + t;tmp2 += + t;
  55. }
  56. }
  57. }
  58. //枚举双顺子
  59. if(tmp2 > && now >= )
  60. {
  61. for(register int i = ;i <= ;++ i)
  62. {
  63. if(cnt[i] > && cnt[i + ] >= && cnt[i + ] >= )
  64. {
  65. cnt[i] -= , cnt[i + ] -= , cnt[i + ] -= ;
  66. tmp2 -= ;
  67. dfs(step + , now - );
  68. register int j = i + ;
  69. int t = ;
  70. for(;j <= ;++ j)
  71. {
  72. if(tmp2 < )break;
  73. if(cnt[j] > ) cnt[j] -= , tmp2 -= , dfs(step + , now - (j - i + ) * );
  74. else break;
  75. }
  76. -- j;
  77. for(;j >= i + ;-- j) cnt[j] += ;
  78. cnt[i] += , cnt[i + ] += , cnt[i + ] += ;
  79. tmp2 += + t;
  80. }
  81. }
  82. }
  83. //枚举单顺子
  84. if(now >= )
  85. {
  86. for(register int i = ;i <= ;++ i)
  87. {
  88. if(cnt[i] && cnt[i + ] && cnt[i + ] && cnt[i + ] && cnt[i + ])
  89. {
  90. -- cnt[i], -- cnt[i + ], -- cnt[i + ], -- cnt[i + ], -- cnt[i + ];
  91. int t3 = , t4 = , t2 = ;
  92. if(cnt[i] == ) -- tmp4, ++ t4;
  93. if(cnt[i + ] == ) -- tmp4, ++ t4;
  94. if(cnt[i + ] == ) -- tmp4, ++ t4;
  95. if(cnt[i + ] == ) -- tmp4, ++ t4;
  96. if(cnt[i + ] == ) -- tmp4, ++ t4;
  97. if(cnt[i] > ) -- tmp3, ++ t3;
  98. if(cnt[i + ] > ) -- tmp3, ++ t3;
  99. if(cnt[i + ] > ) -- tmp3, ++ t3;
  100. if(cnt[i + ] > ) -- tmp3, ++ t3;
  101. if(cnt[i + ] > ) -- tmp3, ++ t3;
  102. if(cnt[i] > ) -- tmp2, ++ t2;
  103. if(cnt[i + ] > ) -- tmp2, ++ t2;
  104. if(cnt[i + ] > ) -- tmp2, ++ t2;
  105. if(cnt[i + ] > ) -- tmp2, ++ t2;
  106. if(cnt[i + ] > ) -- tmp2, ++ t2;
  107. dfs(step + , now - );
  108. register int j = i + ;
  109. for(;j <= ;++ j)
  110. if(cnt[j])
  111. {
  112. -- cnt[j];
  113. if(cnt[j] == )++ t4, -- tmp4;
  114. if(cnt[j] > ) ++ t3, -- tmp3;
  115. if(cnt[j] > ) ++ t2, -- tmp2;
  116. dfs(step + , now - (j - i + ));
  117. }
  118. else break;
  119. -- j;
  120. for(;j >= i + ;-- j) ++ cnt[j];
  121. ++ cnt[i], ++ cnt[i + ], ++ cnt[i + ], ++ cnt[i + ], ++ cnt[i + ];
  122. tmp2 += t2, tmp3 += t3, tmp4 += t4;
  123. }
  124. }
  125. }
  126. //找四带二对牌
  127. if(tmp4 && tmp2 > && now >= )
  128. {
  129. for(register int i = ;i <= ;++ i)
  130. if(cnt[i] == )
  131. for(register int j = ;j <= ;++ j)
  132. if(cnt[j] > && i != j)
  133. for(register int k = j + ;k <= ;++ k)
  134. if(cnt[k] > && i != k)
  135. {
  136. cnt[j] -= ;
  137. cnt[k] -= ;
  138. cnt[i] -= ;
  139. tmp2 -= ;
  140. tmp3 -= ;
  141. tmp4 -= ;
  142. dfs(step + , now - );
  143. cnt[j] += ;
  144. cnt[k] += ;
  145. cnt[i] += ;
  146. tmp2 += ;
  147. tmp3 += ;
  148. tmp4 += ;
  149. }
  150. }
  151. //找四带二单牌
  152. if(tmp4 && now >= )
  153. {
  154. for(register int i = ;i <= ;++ i)
  155. if(cnt[i] == )
  156. {
  157. for(register int j = ;j <= ;++ j)
  158. if(cnt[j] > && i != j)
  159. for(register int k = j + ;k <= ;++ k)
  160. if(cnt[k] > && i != k)
  161. {
  162. int t2 = , t3 = , t4 = ;
  163. -- cnt[j];
  164. -- cnt[k];
  165. if(cnt[j] == ) -- tmp4, ++ t4;
  166. if(cnt[j] > ) -- tmp3, ++ t3;
  167. if(cnt[j] > ) -- tmp2, ++ t2;
  168. if(cnt[k] == ) -- tmp4, ++ t4;
  169. if(cnt[k] > ) -- tmp3, ++ t3;
  170. if(cnt[k] > ) -- tmp2, ++ t2;
  171. cnt[i] -= ;
  172. tmp4 -= ;
  173. tmp3 -= ;
  174. tmp2 -= ;
  175. dfs(step + , now - );
  176. ++ cnt[j];
  177. ++ cnt[k];
  178. cnt[i] += ;
  179. tmp4 += + t4;
  180. tmp3 += + t3;
  181. tmp2 += + t2;
  182. }
  183. if(cnt[] > )
  184. {
  185. cnt[] -= ;
  186. cnt[i] -= ;
  187. tmp4 -= ;
  188. tmp2 -= ;
  189. dfs(step + , now - );
  190. tmp4 += ;
  191. tmp2 += ;
  192. cnt[] += ;
  193. cnt[i] += ;
  194. }
  195. }
  196. }
  197. //找三带二
  198. if(tmp3 && tmp2 && now >= )
  199. {
  200. for(register int i = ;i <= ;++ i)
  201. if(cnt[i] > )
  202. for(register int j = ;j <= ;++ j)
  203. if(cnt[j] > && i != j)
  204. {
  205. cnt[j] -= ;
  206. cnt[i] -= ;
  207. tmp2 -= ;
  208. tmp3 -= ;
  209. dfs(step + , now - );
  210. cnt[j] += ;
  211. cnt[i] += ;
  212. tmp2 += ;
  213. tmp3 += ;
  214. }
  215. }
  216. //找三带一
  217. if(tmp3 && now >= )
  218. {
  219. for(register int i = ;i <= ;++ i)
  220. if(cnt[i] > )
  221. {
  222. cnt[i] -= ;
  223. int t2 = , t3 = , t4 = ;
  224. if(cnt[i] == ) -- tmp4, ++ t4;
  225. if(cnt[i] > ) -- tmp3, ++ t3;
  226. if(cnt[i] > ) -- tmp2, ++ t2;
  227. tmp3 -= ;
  228. tmp2 -= ;
  229. dfs(step + , now - );
  230. cnt[i] += ;
  231. tmp3 += + t3;
  232. tmp2 += + t2;
  233. tmp4 += t4;
  234. for(register int j = ;j <= ;++ j)
  235. if(cnt[j] > && i != j)
  236. {
  237. int t1 = , t2 = , t3 = ;
  238. if(cnt[j] == ) -- tmp4, ++ t4;
  239. if(cnt[j] > ) -- tmp3, ++ t3;
  240. if(cnt[j] > ) -- tmp2, ++ t2;
  241. cnt[j] -= ;
  242. cnt[i] -= ;
  243. tmp3 -= ;
  244. tmp2 -= ;
  245. dfs(step + , now - );
  246. cnt[j] += ;
  247. cnt[i] += ;
  248. tmp4 + t4;
  249. tmp3 += + t3;
  250. tmp2 += + t2;
  251. }
  252. }
  253. }
  254. //找裸四
  255. if(tmp4 > )
  256. {
  257. for(register int i = ;i <= ;++ i)
  258. if(cnt[i] == )
  259. {
  260. cnt[i] -= ;
  261. tmp4 -= ;
  262. tmp3 -= ;
  263. tmp2 -= ;
  264. dfs(step + , now - );
  265. cnt[i] += ;
  266. tmp4 += ;
  267. tmp3 += ;
  268. tmp2 += ;
  269. }
  270. }
  271. //找对子
  272. if(tmp2 > )
  273. {
  274. for(register int i = ;i <= ;++ i)
  275. if(cnt[i] > )
  276. {
  277. cnt[i] -= ;
  278. tmp2 -= ;
  279. dfs(step + , now - );
  280. tmp2 += ;
  281. cnt[i] += ;
  282. }
  283. }
  284. }
  285.  
  286. int main()
  287. {
  288. read(t), read(n);
  289. for(;t;-- t)
  290. {
  291. memset(cnt, , sizeof(cnt));
  292. ans = n;
  293. for(register int j = ;j <= n;++ j)
  294. {
  295. tmp4 = tmp2 = tmp3 = ;
  296. s[] = s[] = ;
  297. scanf("%s", s + );
  298. if(s[] == '') ++ cnt[];
  299. else if(s[] == '') ++ cnt[];
  300. else if(s[] == '' && s[] == '') ++ cnt[];
  301. else if(s[] == '' && s[] == '') ++ cnt[];
  302. else if(s[] == '' && s[] == '') ++ cnt[];
  303. else if(s[] == '' && s[] == '') ++ cnt[];
  304. else if(s[] == '') ++ cnt[];
  305. else ++ cnt[s[] - ''];
  306. for(register int i = ;i <= ;++ i)
  307. {
  308. if(cnt[i] > ) ++ tmp2;
  309. if(cnt[i] > ) ++ tmp3;
  310. if(cnt[i] == ) ++ tmp4;
  311. }
  312. scanf("%s", s + );
  313. }
  314. dfs(, n);
  315. printf("%d\n", ans);
  316. }
  317. return ;
  318. }

TYVJ4239

TYVJ4239 [NOIP2015提高组DayT3]斗地主的更多相关文章

  1. NOIP2015提高组D1T3 斗地主

    问一副排n张,n<=23最少打几次打完,数据组数T<=100. 面向数据编程.. 前30分:乱暴力?没有顺子,把单.对子.炸弹.三张.王炸.三带一判一次即可. 前70分:状压,先预处理哪些 ...

  2. 【题解】NOIP2015提高组 复赛

    [题解]NOIP2015提高组 复赛 传送门: 神奇的幻方 \([P2615]\) 信息传递 \([P2661]\) 斗地主 \([P2668]\) 跳石头 \([P2678]\) 子串 \([P26 ...

  3. [NOIP2015] 提高组 洛谷P2615 神奇的幻方

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

  4. 洛谷-神奇的幻方-NOIP2015提高组复赛

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,--,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

  5. 洛谷 P2678 & [NOIP2015提高组] 跳石头

    题目链接 https://www.luogu.org/problemnew/show/P2678 题目背景 一年一度的“跳石头”比赛又要开始了! 题目描述 这项比赛将在一条笔直的河道中进行,河道中分布 ...

  6. 【数据结构】运输计划 NOIP2015提高组D2T3

    [数据结构]运输计划 NOIP2015提高组D2T3 >>>>题目 [题目描述] 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航 ...

  7. 【二分查找】 跳石头NOIP2015提高组 D2T1

    [二分查找]跳石头NOIP2015提高组 D2T1 >>>>题目 [题目描述] 一年一度的“跳石头”比赛又要开始了! 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石 ...

  8. 刷题总结——子串(NOIP2015提高组)

    题目: 题目背景 NOIP2015 提高组 Day2 T2 题目描述 有两个仅包含小写英文字母的字符串 A 和 B .现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在 ...

  9. noip2015 提高组 day1t1 神奇的幻方

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,--,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

随机推荐

  1. Python(四)基础篇之「文件对象&错误处理」

    [笔记]Python(四)基础篇之「文件对象&错误处理」 2016-12-08 ZOE    编程之魅  Python Notes: ★ 如果你是第一次阅读,推荐先浏览:[重要公告]文章更新. ...

  2. Cesium官方教程10--高级粒子特效

    原文地址:https://cesiumjs.org/tutorials/Particle-Systems-More-Effects-Tutorial/ 高级粒子系统特效 这篇教程学习更多的效果,包括天 ...

  3. PAT甲级——A1008 Elevator

    The highest building in our city has only one elevator. A request list is made up with N positive nu ...

  4. 07_Hibernate多事务并发运行时并发问题检索方式

    什么是事务? 事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位. 事务就是逻辑上的一组操作,要么全都成功,要么全都失败 ...

  5. 【LGP5112】FZOUTSY

    题目 如果是\(hash\)做法的话显然就是把每一个位置后面的\(k\)个位置的hash值拿出来做一个莫队板子就好了 考虑一下牛逼的\(SAM\) 我们完全可以构造出来一棵后缀树,对于每个点找到其祖先 ...

  6. line-height影响排版

    父级div设置了line-height值,子级div会继承line-height.如果不想子级元素继承,给子级元素设置line-height:normal.

  7. 复制字符串 _strdup _wcsdup _mbsdup

    Duplicate strings.函数定义: char *_strdup( const char *strSource ); wchar_t *_wcsdup( const wchar_t *str ...

  8. [转]WPF更换主题

    如果要做到一个应用程序其基本的内容不变,但改变整个应用程序的外观可以这样做: 对于每一套外观定义一个ResourceDictionary 在应用程序中,动态加载此应用程序(或窗体)的Resource ...

  9. SQL中distinct 和 row_number() over() 的区别及用法

    1 前言 在咱们编写 SQL 语句操作数据库中的数据的时候,有可能会遇到一些不太爽的问题,例如对于同一字段拥有相同名称的记录,我们只需要显示一条,但实际上数据库中可能含有多条拥有相同名称的记录,从而在 ...

  10. JavaSE_03_Thread类02

    1.1 线程状态概述 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态.在线程的生命周期中, 有几种状态呢?在API中 java.lang.Thread.State 这个 ...