NOIP2015 斗地主

题目描述

 牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。具体规则如下:

""

输入

第一行包含用空格隔开的2个正整数T,N,表示手牌的组数以及每组手牌的张数。

接下来T组数据,每组数据N行,每行一个非负整数对Ai,Bi,表示一张牌,其中Ai表示牌的数码,Bi表示牌的花色,中间用空格隔开。特别的,我们用1来表示数码A,11表示数码J,12表示数码Q,13表示数码K;黑桃、红心、梅花、方片分别用1-4来表示;小王的表示方法为01,大王的表示方法为02。
 

输出

共T行,每行一个整数,表示打光第T组手牌的最少次数。

样例输入

1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1

样例输出

3
solution:
  1. 在第一眼看到这道题的时候,马上的感觉就是复杂。情况种类太多以至于貌似无法分类,从而导致无从下手的状态。
  2. 但是,我们仔细回想一下问题所在,出牌的主要特征有两种,一种是顺子,一种是重复牌。
  3. 对于重复牌,有两种主要的出法:第一,直接出牌,第二,带着一些其他的牌。
  4. 那么,我们可以考虑将重复牌和顺子分类进行处理。
  5. 对于每一种牌的个数预处理出来,把牌的优先级简化一下,变成1~14(注意这里大小王不能区分开!因为大小王可以组成对子,他们两个是没有优先级的区别的!)
  6. 深搜查找情况,在深搜中进行对顺子的枚举的处理,我们知道,对于每一个不同的顺子形成的状态,都有一个最少操作数的重复牌的操作和它相互满足。
  7. 即,顺子和对子的操作数加起来。正好能将所有的牌都出完。
  8. 深搜中枚举可行的顺子,然后在每一次深搜的时候,处理出了这些顺子之后对应的重复牌的情况,相加,即为当前操作数的总和。
  9. 另外,附带一句,对于重复牌的操作,一个单牌也算在重复牌操作中。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<algorithm>
  5 using namespace std;
  6 __attribute__((optimize("O3")))int read() {
  7     int s=0,f=1;
  8     char ch=getchar();
  9     while(ch>'9'||ch<'0') {
 10         if(ch=='-') {
 11             f=-1;
 12         }
 13         ch=getchar();
 14     }
 15     while(ch>='0'&&ch<='9') {
 16         s=(s<<1)+(s<<3)+(ch^48);
 17         ch=getchar();
 18     }
 19     return s*f;
 20 }
 21 int T,n,kind[25],ans,num[25];
 22 __attribute__((optimize("O3")))int get(int x) {
 23     int temp=0;
 24     if(x==1) {
 25         temp=12;
 26     } else {
 27         if(x==2) {
 28             temp=13;
 29         } else {
 30             if(x==0) {
 31                 temp=14;
 32             } else {
 33                 if(x>=3&&x<=13) {
 34                     temp=x-2;
 35                 }
 36             }
 37         }
 38     }
 39     return temp;
 40 }
 41 __attribute__((optimize("O3")))int card() {
 42     int b[6]= {0},ans=0;
 43     for(int i=1; i<=15; i++) {
 44         b[kind[i]]++;
 45     }
 46     while(b[4]&&b[2]>=2) {
 47         ans++;
 48         b[4]--;
 49         b[2]-=2;
 50     }
 51     while(b[4]&&b[1]>=2) {
 52         ans++;
 53         b[4]--;
 54         b[1]-=2;
 55     }
 56     while(b[3]&&b[1]>=1) {
 57         ans++;
 58         b[3]--;
 59         b[1]--;
 60     }
 61     while(b[3]&&b[2]>=1) {
 62         ans++;
 63         b[3]--;
 64         b[2]--;
 65     }
 66     ans+=b[1]+b[2]+b[3]+b[4];
 67     return ans;
 68 }
 69 __attribute__((optimize("O3")))void dfs(int step) {
 70     if(step>ans) {
 71         return ;
 72     }
 73     int x=card();
 74     ans=min(step+x,ans);
 75     for(int i=1; i<=11; i++) {
 76         int j;
 77         for(j=i; kind[j]>=3&&j<=12; j++);
 78         if(j-i<2) {
 79             continue;
 80         }
 81         for(int k=j; k-i>=2; k--) {
 82             for(int h=i; h<k; h++) {
 83                 kind[h]-=3;
 84             }
 85             dfs(step+1);
 86             for(int h=i; h<k; h++) {
 87                 kind[h]+=3;
 88             }
 89         }
 90     }
 91     for(int i=1; i<=10; i++) {
 92         int j;
 93         for(j=i; kind[j]>=2&&j<=12; j++);
 94         if(j-i<3) {
 95             continue;
 96         }
 97         for(int k=j; k-i>=3; k--) {
 98             for(int h=i; h<k; h++) {
 99                 kind[h]-=2;
100             }
101             dfs(step+1);
102             for(int h=i; h<k; h++) {
103                 kind[h]+=2;
104             }
105         }
106     }
107     for(int i=1; i<=8; i++) {
108         int j;
109         for(j=i; kind[j]>=1&&j<=12; j++);
110         if(j-i<5) {
111             continue;
112         }
113         for(int k=j; k-i>=5; k--) {
114             for(int h=i; h<k; h++) {
115                 kind[h]--;
116             }
117             dfs(step+1);
118             for(int h=i; h<k; h++) {
119                 kind[h]++;
120             }
121         }
122     }
123 }
124 __attribute__((optimize("O3")))int main() {
125     T=read();
126     n=read();
127     while(T--) {
128         ans=0x7ffffff;
129         memset(kind,0,sizeof(kind));
130         for(int i=1; i<=n; i++) {
131             int x=read(),y=read();
132             int ji=get(x);
133             kind[ji]++;
134             //cout<<ji<<endl;
135         }
136         ans=card();
137         dfs(0);
138         printf("%d\n",ans);
139     }
140     return 0;
141 }

 

 
posted @ 2017-07-30 19:10  Forever_goodboy  阅读(273)  评论(0编辑  收藏  举报