TYVJ4239 [NOIP2015提高组DayT3]斗地主

Posted 嘒彼小星

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TYVJ4239 [NOIP2015提高组DayT3]斗地主相关的知识,希望对你有一定的参考价值。

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

 

以上是关于TYVJ4239 [NOIP2015提高组DayT3]斗地主的主要内容,如果未能解决你的问题,请参考以下文章

如何评价NOIP2015提高组复赛试题

[NOIP2015 提高组] 运输计划

如何评价NOIP2015提高组复赛试题

noip2015提高组

noip 2015 提高组

NOIP2015提高组