C++——NOIP2015提高组day1 t3——斗地主

来源:互联网 发布:淘宝网怎么找秒杀 编辑:程序博客网 时间:2024/05/07 21:53

题目描述

牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的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 来表示;小王的表示方法为 0 1,大王的表示方法为 0 2 。

输出格式

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

样例数据 1

输入

1 8 
7 4 
8 4 
9 1 
10 4 
11 1 
5 1 
1 4 
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

输出

6

备注

【样例1说明】 
共有 1 组手牌,包含 8 张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张牌(黑桃5)以及对子牌(黑桃A以及方片A)在3次内打光。

【数据范围】 
对于不同的测试点,我们约定手牌组数 T 与张数 n 的规模如下:


#include<stdio.h>#define C(x,y,z) \while(num[x]&&num[y]>z-1){\--num[x];\num[y]-=z;\++tot;\}#define A(x,y) \for(__int32 i=2;i<=13;++i){\register __int32 j=i;\while(a[j]>=x) ++j;\if(j-i>=y)\for(__int32 k=i+y-1;k<j;++k){\for(__int32 p=i;p<=k;++p) a[p]-=x;\dfs(step+1);\for(__int32 p=i;p<=k;++p) a[p]+=x;\}\}__int32 n,t,ans;__int32 a[24],num[24];extern "C" _CRTIMP void* __cdecl __MINGW_NOTHROWmemset (void*, __int32, size_t);__int32 readint(){__int32 i=0;__int8 ch;for(ch=getchar();ch<'0'||ch>'9';ch=getchar());for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0';return i;}__int32 out(){memset(num,0,sizeof(num));for(__int32 i=0;i<=13;++i) ++num[a[i]];register __int32 tot=0;C(4,2,2)C(4,1,2)C(4,2,1)C(3,2,1)C(3,1,1)return tot+num[1]+num[2]+num[3]+num[4];}void dfs(__int32 step){if(step>=ans) return;register __int32 t=out();if(t+step<ans) ans=t+step;A(3,2)A(2,3)A(1,5)}int main(){t=readint();n=readint();while(t--){memset(a,0,sizeof(a));register __int32 x,y;for(__int32 i=1;i<=n;++i){x=readint();y=readint();x==1 ? x=13 : x ? --x : false ;++a[x];}ans=0x7fffffff;dfs(0);__int32 nu=0;__int8 c[10];while(ans) c[++nu]=(ans%10)+48,ans/=10;while(nu) putchar(c[nu--]);putchar('\n');}return 0;}


原创粉丝点击