设为首页 加入收藏

TOP

NOIP2015斗地主题解 7.30考试(一)
2017-10-11 18:34:33 】 浏览:1181
Tags:NOIP2015 斗地主 题解 7.30 考试

  

问题 B: NOIP2015 斗地主

时间限制: 3 Sec  内存限制: 1024 MB

题目描述

 牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的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

提示

 共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张

 

  这道题为NOIP2015第一天第三题。属于爆搜类,没有任何算法,就是模拟加爆搜。由于有不同种打法,dfs分为好几层,本着先大后小便于剪枝的原则,先出顺子,再带牌,最后散着出。

  首先,花色对结果无影响,其次大小王对结果是否有贡献只看是否出现其中之一,出现结果+1即可,未出现就不必管了(吐槽一下题目描述,没说四带二不算俩王,但测试点中确实不带)。还有一点值得注意的是大小顺序,首先是2不算顺子,其次1比3~13都大,因此可以把大小统一减2,1、2改为12、13便于使用。

  先预处理出各个数字(以下都为预处理后的数字)的个数,开始分层爆搜。先提前说明各个数组,la[]为各个数字还剩几个没打,num[i]为数量为i的同数字牌还有几个

  第一至三层为顺子,它们可以搜索到自己,因为一套牌可以出现多个顺子,至于顺子的长度,从大到小进行枚举,原理见上然后将搜索完的目标再次指向自己,在函数最后向下一层搜索。

  第四,五层为带,四层为四带二,要注意是四带二不是四带一,因为这个卡了55%,带对带单都可以,又因为可以同时出四带两个单和四带两个双,因此需要引入一个bool型变量确认该次搜索由哪里传下来,若为上层则四带双和四带单都单独搜索,四带双继续指向本层,bool改变,只搜四带单,三同理。

  第五层就是处理散牌了,不解释。

  最后膜拜?大犇,有一个剪枝,若到盖层走的步数以比当前最优解大,则直接返回,貌似省了不少时间。

  本来就是搜索题,只能说这些了,其实主要还是代码能力和脑洞

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<queue>
  6 #include<algorithm>
  7 #include<cmath>
  8 using namespace std;
  9 int t,n,ans=0x7fffffff;
 10 int sum[14],la[14],num[5];
 11 void dfs6(int js){
 12     if(js>=ans)return;
 13     int jj=0;
 14     for(int i=4;i>=1;i--)
 15         jj+=num[i];
 16     ans=min(ans,jj+js);
 17     return;
 18 }
 19 void dfs5(int js,bool pd){ //3 _
 20     if(js>=ans)return;
 21     int nn[5];
 22     memcpy(nn,num,sizeof(num));
 23     if(!pd)
 24     {
 25         for(int i=num[3];i>=1;i--)
 26         {
 27             if(num[2]>=i)
 28             {
 29                 memcpy(num,nn,sizeof(num));
 30                 num[3]-=i;
 31                 num[2]-=i;
 32                 dfs5(js+i,1);
 33                 memcpy(num,nn,sizeof(num));//记得还原,否则判断num[]将会失误。下同。 
 34             }
 35         }
 36     }
 37     for(int i=num[3];i>=1;i--)
 38     {
 39         if(num[1]>=i)
 40         {
 41             memcpy(num,nn,sizeof(num));
 42             num[3]-=i;
 43             num[1]-=i;
 44             dfs6(js+i);
 45             memcpy(num,nn,sizeof(num));
 46         }
 47     }
 48     memcpy(num,nn,sizeof(nn));
 49     dfs6(js);
 50 }
 51 void dfs4(int js,bool pd){      //4 2    
 52     if(js>=ans)    return;
 53     int nn[5];
 54     if(!pd)
 55     {
 56         memset(num,0,sizeof(num));
 57         for(int i=1;i<=13;i++) num[la[i]]++;
 58         memcpy(nn,num,sizeof(num));
 59         for(int i=num[4];i>=1;i--)
 60         {
 61             if(num[2]>=i*2)
 62             {
 63                 memcpy(num,nn,sizeof(nn));
 64                 num[4]-=i;
 65                 num[2]-=i*2;
 66                 dfs4(js+i,1);
 67                 memcpy(num,nn,sizeof(nn)); 
 68             }        
 69         }
 70     }
 71     if(pd) memcpy(nn,num,sizeof(num));
 72     for(int i=num[4];i>=1;i--)
 73     {
 74         if(num[1]>=i*2)
 75         {
 76             memcpy(num,nn,sizeof(nn));
 77             num[4]-=i;
 78             num[1]-=i*2;
 79             dfs5(js+i,0);
 80             memcpy(num,nn,sizeof(nn));
 81         }
 82     }
 83     memcpy(num,nn,sizeof(nn));
 84     dfs5(js,0);
 85 }
 86 void dfs3(int js){    //1s
 87     if(js>=ans) return;
 88     int ll[14];
 89     memcpy(ll,la,sizeof(la
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇HDU 6035---Colorful Tree(树形D.. 下一篇[BZOJ1500][NOI2005]维修数列 解..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目