TYVJ P1092 麻将
题目:
http://tyvj.cn/Problem_Show.asp?id=1092
题解:
不解释………………自己去看代码吧……………………
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4
5 using namespace std;
6
7 int num[10][20],num2[10][20],t;
8
9 char s[40];
10
11 bool dfs(int now)
12 {
13 if (now==5)
14 {
15 for (int a=1;a<=3;a++)
16 for (int b=1;b<=9;b++)
17 if (num[a][b]!=0)
18 {
19 if (num[a][b]!=2) return false;
20 }
21 return true;
22 }
23 for (int a=1;a<=3;a++)
24 for (int b=1;b<=9;b++)
25 if (num[a][b]!=0)
26 {
27 if (num[a][b+1]!=0 && num[a][b+2]!=0)
28 {
29 num[a][b]--;
30 num[a][b+1]--;
31 num[a][b+2]--;
32 if (dfs(now+1))
33 {
34 num[a][b]++;
35 num[a][b+1]++;
36 num[a][b+2]++;
37 return true;
38 }
39 num[a][b]++;
40 num[a][b+1]++;
41 num[a][b+2]++;
42 }
43 if (num[a][b]>=3)
44 {
45 num[a][b]-=3;
46 if (dfs(now+1))
47 {
48 num[a][b]+=3;
49 return true;
50 }
51 num[a][b]+=3;
52 }
53 }
54 return false;
55 }
56
57 bool check()//检查是否能和
58 {
59 return dfs(1);
60 }
61
62 int work1()//平和(一番):4个顺子组成
63 {
64 for (int a=1;a<=3;a++)
65 for (int b=1;b<=9;b++)
66 if (num[a][b]>=2)
67 {
68 for (int c=1;c<=3;c++)
69 for (int d=1;d<=9;d++)
70 num2[c][d]=num[c][d];
71 num2[a][b]-=2;
72 bool able=true;
73 for (int c=1;c<=3;c++)
74 {
75 if (!able) break;
76 for (int d=1;d<=9;d++)
77 if (num2[c][d]!=0)
78 {
79 if (num2[c][d+1]==0 || num2[c][d+2]==0)
80 {
81 able=false;
82 break;
83 }
84 num2[c][d]--;
85 num2[c][d+1]--;
86 num2[c][d+2]--;
87 d--;
88 }
89 }
90 if (able) return 1;
91 }
92 return 0;
93 }
94
95 int work2()//断幺九(一番):胡牌的时候手上只有2-8的数字组成的牌型
96 {
97 if (num[1][1] || num[2][1] || num[3][1] || num[1][9] || num[2][9] || num[3][9]) return 0;
98 else return 1;
99 }
100
101 int work3()//一杯口(一番):同花色同数值的顺子两组
102 {
103 for (int a=1;a<=3;a++)
104 for (int b=1;b<=9;b++)
105 if (num[a][b]>=2)
106 {
107 for (int c=1;c<=3;c++)
108 for (int d=1;d<=9;d++)
109 num2[c][d]=num[c][d];
110 num2[a][b]-=2;
111 bool able=true;
112 for (int c=1;c<=3;c++)
113 {
114 if (!able) break;
115 for (int d=1;d<=9;d++)
116 if (num2[c][d]!=0)
117 {
118 if (num2[c][d]>=2 && num2[c][d+1]>=2 && num2[c][d+2]>=2) return 1;
119 if (num2[c][d+1]==0 || num2[c][d+2]==0)
120 {
121 able=false;
122 break;
123 }
124 num2[c][d]--;
125 num2[c][d+1]--;
126 num2[c][d+2]--;
127 d--;
128 }
129 }
130 }
131 return 0;
132 }
133
134 bool dfs2(int now)
135 {
136 if (now==5) return true;
137 for (int a=1;a<=3;a++)
138 for (int b=1;b<=9;b++)
139 if (num2[a][b]!=0)
140 {
141 if (num2[a][b+1]!=0 && num2[a][b+2]!=0 && (b==1 || b+2==9))
142 {
143 num2[a][b]--;
144 num2[a][b+1]--;
145 num2[a][b+2]--;
146 if (dfs2(now+1)) return true;
147 num2[a][b]++;
148 num2[a][b+1]++;
149 num2[a][b+2]++;
150 }
151 if (num2[a][b]>=3 && (b==1 || b==9))
152 {
153 num2[a][b]-=3;
154 if (dfs2(now+1)) return true;
155 num2[a][b]+=3;
156 }
157 }
158 return false;
159 }
160
161 int work4()//混全带幺九(一番):全部的顺子,刻子中都含有数字1或9
162 {
163 for (int a=1;a<=3;a++)
164 for (int b=1;b<=9;b++)
165 if (num[a][b]>=2)
166 {
167 for (int c=1;c<=3;c++)
168 for (int d=1;d<=9;d++)
169 num2[c][d]=num[c][d];
170 num2[a][b]-=2;
171 if (dfs2(1)) return 1;
172 }
173 return 0;
174 }
175
176 int work5()//三色同顺(一番):三种花色同数值的顺子各一组
177 {
178 for (int a=1;a<=3;a++)
179 for (int b=1;b<=9;b++)
180 if (num[a][b]>=2)
181 {
182 for (int c=1;c<=3;c++)
183 for (int d=1;d<=9;d++)
184 num2[c][d]=num[c][d];
185 num2[a][b]-=2;
186 for (int c=1;c<=9;c++)
187 if (num2[1][c] && num2[2][c] && num2[3][c] && num2[1][c+1] && num2[2][c+1] && num2[3][c+1] && num2[1][c+2] && num2[2][c+2] && num2[3][c+2])
188 {
189 num2[1][c]--;num2[1][c+1]--;num2[1][c+2]--;
190 num2[2][c]--;num2[2][c+1]--;num2[2][c+2]--;
191 num2[3][c]--;num2[3][c+1]--;num2[3][c+2]--;
192 bool able,find=false;
193 for (int c=1;c<=3;c++)
194 {
195 if (find) break;
196 for (int d=1;d<=9;d++)
197 if (num2[c][d]!=0)
198 {
199 find=true;
200 if (num2[c][d]==3) able=true;
201 else
202 {
203 if (num2[c][d]==1 && num2[c][d+1]==1 && num2[c][d+2]==1) able=true;
204 else able=false;
205 }
206 break;
207 }
208 }
209 if (able) return 1;
210 }
211 }
212 return 0;
213 }
214
215 int work6()//一气贯通(一番):由同花色一至九组成顺子
216 {
217 for (int a=1;a<=3;a++)
218 for (int b=1;b<=9;b++)
219 if (num[a][b]>=2)
220 {
221 for (int c=1;c<=3;c++)
222 for (int d=1;d<=9;d++)
223 num2[c][d]=num[c][d];
224 num2[a][b]-=2;
225 for (int c=1;c<=3;c++)
226 if (num2[c][1] && num2[c][2] && num2[c][3] && num2[c][4] && num2[c][5] && num2[c][6] && num2[c][7] && num2[c][8] && num2[c][9])
227 {
228 num2[c][1]--;
229 num2[c][2]--;
230 num2[c][3]--;
231 num2[c][4]--;
232 num2[c][5]--;
233 num2[c][6]--;
234 num2[c][7]--;
235 num2[c][8]--;
236 num2[c][9]--;
237 bool able=false,find=false;
238 for (int d=1;d<=3;d++)
239 {
240 if (find) break;
241 for (int e=1;e<=9;e++)
242 if (num2[d][e]!=0)
243 {
244 find=true;
245 if (num2[d][e]==3) able=true;
246 else
247 {
248 if (num2[d][e+1]==1 && num2[d][e+2]==1) able=true;
249 else able=false;
250 }
251 break;
252 }
253 }
254 if (able) return 1;
255 }
256 }
257 return 0;
258 }
259
260 int work7()//一色三顺(两番):同花色同数值顺子三组
261 {
262 for (int a=1;a<=3;a++)
263 for (int b=1;b<=9;b++)
264 if (num[a][b]>=2)
265 {
266 for (int c=1;c<=3;c++)
267 for (int d=1;d<=9;d++)
268 num2[c][d]=num[c][d];
269 num2[a][b]-=2;
270 for (int c=1;c<=3;c++)
271 for (int d=1;d<=9;d++)
272 if (num2[c][d]>=3 && num2[c][d+1]>=3 && num2[c][d+2]>=3)
273 {
274 num2[c][d]-=3;
275 num2[c][d+1]-=3;
276 num2[c][d+2]-=3;
277 bool able=false,find=false;
278 for (int d=1;d<=3;d++)
279 {
280 if (find) break;
281 for (int e=1;e<=9;e++)
282 if (num2[d][e]!=0)
283 {
284 find=true;
285 if (num2[d][e]==3) able=true;
286 else
287 {
288 if (num2[d][e+1]==1 && num2[d][e+2]==1) able=true;
289 else able=false;
290 }
291 break;
292 }
293 }
294 if (able) return 2;
295 }
296 }
297 return 0;
298 }
299
300 int work8()//对对和(两番):四组刻子
301 {
302 for (int a=1;a<=3;a++)
303 for (int b=1;b<=9;b++)
304 if (num[a][b]>=2)
305 {
306 for (int c=1;c<=3;c++)
307 for (int d=1;d<=9;d++)
308 num2[c][d]=num[c][d];
309 num2[a][b]-=2;
310 bool able=true;
311 for (int c=1;c<=3;c++)
312 for (int d=1;d<=9;d++)
313 if (num2[c][d]!=0)
314 {
315 if (num2[c][d]!=3) able=false;
316 }
317 if (able) return 2;
318 }
319 return 0;
320 }
321
322 int work9()//两杯口(三番):由两组不同的一杯口组成
323 {
324 for (int a=1;a<=3;a++)
325 for (int b=1;b<=9;b++)
326 if (num[a][b]>=2)
327 {
328 for (int c=1;c<=3;c++)
329 for (int d=1;d<=9;d++)
330 num2[c][d]=num[c][d];
331 num2[a][b]-=2;
332 bool able=true,find=false;
333 for (int c=1;c<=3;c++)
334 {
335 if (find) break;
336 for (int d=1;d<=9;d++)
337 if (num2[c][d]!=0)
338 {
339 find=true;
340 if (num2[c][d]<2 || num2[c][d+1]<2 || num2[c][d+2]<2)
341 {
342 able=false;
343 break;
344 }
345 else
346 {
347 num2[c][d]-=2;
348 num2[c][d+1]-=2;
349 num2[c][d+2]-=2;
350 bool find=false;
351 for (int e=1;e<=3;e++)
352 {
353 if (find) break;
354 for (int f=1;f<=9;f++)
355 if (num2[e][f]!=0)
356 {
357 find=true;
358 if (e==c && f==d)
359 {
360 able=false;
361 break;
362 }
363 if (num2[e][f]!=2 || num2[e][f+1]!=2 || num2[e][f+2]!=2) able=false;
364 break;
365 }
366 }
367 break;
368 }
369 }
370 }
371 if (able) return 3;
372 }
373 return 0;
374 }
375
376 int work10()//三色同刻(三番):三种花色同数值的刻子各一组
377 {
378 for (int a=1;a<=3;a++)
379 for (int b=1;b<=9;b++)
380 if (num[a][b]>=2)
381 {
382 for (int c=1;c<=3;c++)
383 for (int d=1;d<=9;d++)
384 num2[c][d]=num[c][d];
385 num2[a][b]-=2;
386 for (int c=1;c<=9;c++)
387 if (num2[1][c]>=3 && num2[2][c]>=3 && num2[3][c]>=3)
388 {
389 num2[1][c]-=3;
390 num2[2][c]-=3;
391 num2[3][c]-=3;
392 bool able=false,find=false;
393 for (int d=1;d<=3;d++)
394 {
395 if (find) break;
396 for (int e=1;e<=9;e++)
397 if (num2[d][e]!=0)
398 {
399 find=true;
400 if (num2[d][e]==3) able=true;
401 else
402 {
403 if (num2[d][e+1]==1 && num2[d][e+2]==1) able=true;
404 else able=false;
405 }
406 break;
407 }
408 }
409 if (able) return 3;
410 }
411 }
412 return 0;
413 }
414
415 int work11()//清一色(六番):全部由同一种花色的顺子,刻子及雀头组成
416 {
417 for (int a=1;a<=3;a++)
418 {
419 int nowsum=0;
420 for (int b=1;b<=9;b++)
421 nowsum+=num[a][b];
422 if (nowsum==14) return 6;
423 }
424 return 0;
425 }
426
427 int work12()//清老头(六番):全部由1或9的刻子和雀头组成
428 {
429 for (int a=1;a<=3;a++)
430 for (int b=2;b<=8;b++)
431 if (num[a][b]) return 0;
432 return 6;
433 }
434
435 int main()
436 {
437 scanf("%d",&t);
438 for (int a=1;a<=t;a++)
439 {
440 scanf("%s",s+1);
441 memset(num,0,sizeof(num));
442 for (int a=1;a<=14;a++)
443 {
444 switch(s[a*2])
445 {
446 case 'w':
447 {
448 num[1][s[a*2-1]-'0']++;
449 break;
450 }
451 case 's':
452 {
453 num[2][s[a*2-1]-'0']++;
454 break;
455 }
456 case 't':
457 {
458 num[3][s[a*2-1]-'0']++;
459 break;
460 }
461 }
462 }
463 if (!check())//检查是否能和
464 {
465 printf("0\n");
466 continue;
467 }
468 int ans=0;
469 ans+=work1();//平和(一番):4个顺子组成
470 ans+=work2();//断幺九(一番):胡牌的时候手上只有2-8的数字组成的牌型
471 ans+=work3();//一杯口(一番):同花色同数值的顺子两组
472 ans+=work4();//混全带幺九(一番):全部的顺子,刻子中都含有数字1或9
473 ans+=work5();//三色同顺(一番):三种花色同数值的顺子各一组
474 ans+=work6();//一气贯通(一番):由同花色一至九组成顺子
475 ans+=work7();//一色三顺(两番):同花色同数值顺子三组
476 ans+=work8();//对对和(两番):四组刻子
477 ans+=work9();//两杯口(三番):由两组不同的一杯口组成
478 ans+=work10();//三色同刻(三番):三种花色同数值的刻子各一组
479 ans+=work11();//清一色(六番):全部由同一种花色的顺子,刻子及雀头组成
480 ans+=work12();//清老头(六番):全部由1或9的刻子和雀头组成
481 printf("%d\n",ans);
482 }
483 return 0;
484 }