P2668 斗地主

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
",ans);
117     }
118     return 0;
119 } 
原文地址:https://www.cnblogs.com/mjtcn/p/6891513.html