【NOIP2015】鬥地主

P2431 - 【NOIP2015】鬥地主

Description

牛牛最近迷上了一種叫鬥地主的撲克遊戲。鬥地主是一種 使用黑桃、紅心、梅花、方片的A到K加上大小王的共54張牌來進行的撲克牌遊戲。在鬥地主中,牌的大小關係根據牌的數碼錶示如 下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色並不對牌的大小產生影響。每一局遊戲中,一副手牌由n張牌組成。遊戲者每 次能夠根據規定的牌型進行出牌,首先打光本身的手牌一方取得遊戲的勝利。
如今,牛牛隻想知道,對於本身的若干組手牌,分別最少須要多少次出牌能夠將它們打光。請你幫他解決這個問題。
須要注意的是,本題中游戲者每次能夠出手的牌型與通常的鬥地主類似而略有不一樣。
具體規則以下: ios

P

Input

第一行包含用空格隔開的2個正整數Tn,表示手牌的組數以及每組手牌的張數。
接下來T組數據,每組數據n行,每行一個非負整數對aibi表示一張牌,其中ai示牌的數碼,bi表示牌的花色,中間用空格隔開。 特別的,咱們用1來表示數碼A,11表示數碼J,12表示數碼Q,13表示數碼K;黑桃、紅心、梅花、方片分別用1-4來表示;小王的表示方法爲01,大 王的表示方法爲02。ui

Output

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

Sample Input

樣例輸入1:
1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1 code

樣例輸入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 blog

Sample Output

樣例輸出1:
3 遊戲

樣例輸出2:
6ip

 

貪心的想一想,最好是先一次性出多點. 因此先打三順子,再打雙順子,再打單順子. 而後剩餘的牌直接按照出牌的數量從大到小打. 由於可以打四帶兩對確定打掉四帶兩對最優。 string

注意搜順子的時候不必定要把順子所有打出去. 由於可能把順子直接打出去以後剩的都是單牌了。 而後很坑的是, 要把王炸當作一對牌,就是說王炸能夠被帶出去?!?!?!. it

 

 1 #include<set>
 2 #include<map>
 3 #include<queue>
 4 #include<stack>
 5 #include<ctime>
 6 #include<cmath>
 7 #include<string>
 8 #include<vector>
 9 #include<cstdio>
10 #include<cstdlib>
11 #include<cstring>
12 #include<iostream>
13 #include<algorithm>
14 using namespace std;
15 int sum[20],ans=100,c[10];
16 int IDA_star()
17 {
18   memset(c,0,sizeof(c));
19   int tot=0;
20   for(int i=1;i<=14;i++) c[sum[i]]++;
21   while(c[4] && c[2]>1) c[4]--,c[2]-=2,tot++;
22   while(c[4] && c[1]>1) c[4]--,c[1]-=2,tot++;
23   while(c[4] && c[2]) c[4]--,c[2]--,tot++;
24   while(c[3] && c[2]) c[3]--,c[2]--,tot++;
25   while(c[3] && c[1]) c[3]--,c[1]--,tot++;
26   return tot+c[1]+c[2]+c[3]+c[4];
27 }
28 void search(int step)
29 {
30   if(step>=ans) return;
31   for(int i=1;i<=11;i++) //三順子
32     {
33       int j;if(sum[i]<3) continue;
34       for(j=i;sum[j]>=3 && j<=12;j++);
35       j--;
36       if(j-i+1>=2){
37     for(int j2=i+1;j2<=j;j2++){
38       for(int k=i;k<=j2;k++) sum[k]-=3;
39       search(step+1);
40       for(int k=i;k<=j2;k++) sum[k]+=3;
41     }
42       }
43     }
44   for(int i=1;i<=10;i++) //雙順子
45     {
46       int j;if(sum[i]<2) continue;
47       for(j=i;sum[j]>=2 && j<=12;j++);
48       j--;
49       if(j-i+1>=3){
50     for(int j2=i+2;j2<=j;j2++){
51       for(int k=i;k<=j2;k++) sum[k]-=2;
52       search(step+1);
53       for(int k=i;k<=j2;k++)sum[k]+=2;
54     }
55       }
56     }
57   for(int i=1;i<=8;i++) //單順子
58     {
59       int j;if(sum[i]<1) continue;
60       for(j=i;sum[j]>=1 && j<=12;j++);
61       j--;
62       if(j-i+1>=5){
63     for(int j2=i+4;j2<=j;j2++){
64       for(int k=i;k<=j2;k++) sum[k]--;
65       search(step+1);
66       for(int k=i;k<=j2;k++) sum[k]++;
67     }
68       }
69     }
70   int cut=IDA_star();
71   if(step+cut>=ans) return;
72   else ans=step+cut;
73 }
74 int main()
75 {
76   freopen("!.in","r",stdin);
77   freopen("!.out","w",stdout);
78   int T,n;
79   scanf("%d%d",&T,&n);
80   while(T){
81     ans=100;
82     memset(sum,0,sizeof(sum));
83     T--;int x,y;
84     for(int i=1;i<=n;i++){
85       scanf("%d%d",&x,&y);
86       if(x==0) sum[14]++;
87       else sum[((x+10)%13)+1]++;
88     }
89     search(0);
90     printf("%d\n",ans);
91   }
92   return 0;
93 }
相關文章
相關標籤/搜索