1. 程式人生 > >P2668 鬥地主

P2668 鬥地主

其中 tool -- 正整數 現在 ring left hang ==

P2668 鬥地主

題目描述

牛牛最近迷上了一種叫鬥地主的撲克遊戲。鬥地主是一種使用黑桃、紅心、梅花、方片的A到K加上大小王的共54張牌來進行的撲克牌遊戲。在鬥地主中,牌的大小關系根據牌的數碼表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色並不對牌的大小產生影響。每一局遊戲中,一副手牌由n張牌組成。遊戲者每次可以根據規定的牌型進行出牌,首先打光自己的手牌一方取得遊戲的勝利。

現在,牛牛只想知道,對於自己的若幹組手牌,分別最少需要多少次出牌可以將它們打光。請你幫他解決這個問題。

需要註意的是,本題中遊戲者每次可以出手的牌型與一般的鬥地主相似而略有不同。

具體規則如下:

技術分享

輸入輸出格式

輸入格式:

第一行包含用空格隔開的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的規模如下:

技術分享

數據保證:所有的手牌都是隨機生成的。

分析:深搜。深搜順子出現的各種情況,然後加上 三帶一,三帶二,四帶一,四帶二,四帶兩個對子,單出一張牌,兩張牌,三張牌,四張牌的次數

  1 #include<cstdio>
  2 #include<cstring>
  3 
  4 using namespace std;
  5 const int N = 20;
  6 
  7 int puke[N];
  8 int num[N];
  9 int t,n,ans;
 10 
 11 int chupai()
 12 {
 13     memset(num,0,sizeof(num));
 14     for(int i=0;i<=13;++i)
 15         num[puke[i]]++;
 16     int tot = 0;
 17     while(num[4] && num[2]>1)
 18     {
 19         num[4]--;
 20         num[2] -= 2;
 21         tot++; 
 22     }
 23     while(num[4] && num[1]>1)
 24     {
 25         num[4]--;
 26         num[1] -= 2;
 27         tot++;
 28     }
 29     while(num[4] && num[2])
 30     {
 31         num[4]--;
 32         num[2]--;
 33         tot++;
 34     }
 35     while(num[3] && num[2])
 36     {
 37         num[3]--;
 38         num[2]--;
 39         tot++;
 40     }
 41     while(num[3] && num[1])
 42     {
 43         num[3]--;
 44         num[1]--;
 45         tot++;
 46     }
 47     return tot + num[1] + num[2] + num[3] + num[4];
 48 }
 49 
 50 void dfs(int step)
 51 {
 52     if(step>=ans) return;
 53     int tmp = chupai();
 54     if(tmp+step<ans) ans = tmp+step;
 55     for(int i=2;i<=13;++i)    //三個的順子 
 56     {    
 57         int j = i;
 58         while(puke[j]>=3) j++;
 59         if(j-i>=2)
 60             for(int p=i+1;p<=j-1;++p)
 61             {
 62                 for(int k=i;k<=p;++k)
 63                     puke[k] -= 3;
 64                 dfs(step+1);
 65                 for(int k=i;k<=p;++k)
 66                     puke[k] += 3;
 67             }
 68     }
 69     for(int i=2;i<=13;++i)    //兩個的順子 
 70     {    
 71         int j = i;
 72         while(puke[j]>=2) j++;
 73         if(j-i>=3)
 74             for(int p=i+2;p<=j-1;++p)
 75             {
 76                 for(int k=i;k<=p;++k)
 77                     puke[k] -= 2;
 78                 dfs(step+1);
 79                 for(int k=i;k<=p;++k)
 80                     puke[k] += 2;
 81             }
 82     }
 83     for(int i=2;i<=13;++i)    //一個的順子 
 84     {    
 85         int j = i;
 86         while(puke[j]>=1) j++;
 87         if(j-i>=5)
 88             for(int p=i+4;p<=j-1;++p)
 89             {
 90                 for(int k=i;k<=p;++k)
 91                     puke[k]--;
 92                 dfs(step+1);
 93                 for(int k=i;k<=p;++k)
 94                     puke[k]++;
 95             }
 96     }
 97 }
 98 int main()
 99 {
100     freopen("landlords.in","r",stdin);
101     freopen("landlords.out","w",stdout);
102     scanf("%d%d",&t,&n);
103     while(t--)
104     {
105         memset(puke,0,sizeof(puke));
106         for(int i=1;i<=n;++i)
107         {
108             int x,y;
109             scanf("%d%d",&x,&y);
110             if(x==1) x = 13;
111             else if(x) x--;
112             puke[x]++;
113         }
114         ans = 99999999;
115         dfs(0);
116         printf("%d\n",ans);
117     }
118     return 0;
119 } 

P2668 鬥地主