zoukankan      html  css  js  c++  java
  • 斗地主[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

    1 8

    7 4

    8 4

    9 1

    10 4

    11 1

    5 1

    1 4

    1 1

    样例输出1

    3

    样例说明:共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张牌(黑桃5)以及对子牌(黑桃A以及方片A)在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

    数据范围

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

    数据保证:所有的手牌都是随机生成的。

    时空限制

    1024M,2s

    【题解】

           一道喜闻乐见的大模拟大搜索题,看到了之后就一直跃跃欲试想做一做。考试主要的时间都用来打这道题,刚开始是bfs,卡到直接死机。后来改成dfs,成功过了样例,水过6个点。总觉得dfs不如bfs适合找最优解,但是其实dfs也可以通过剪枝遏制不必要的搜索,而像这种情况非常多的题目bfs要尝试每一种情况的下一步,消耗过大反而不适宜。

            正解也是暴搜,但是搜得比我有技巧多了。尽量先打出较多牌来剪枝,最后那些没有被各种特效打出去的牌就直接一视同仁st++就好了。在考试代码上加了最后这条优化瞬间从TLE变成AC,其实想想打单种牌这么简单的事,一句话就解决了何必再来一层dfs呢~据说这道题体现了用各种条件层层剪枝的重要性,但是对于我来说,还是对所谓的“高明的处理方法”更有体会吧。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int t,n,p[20],a1,a2,jg;
    bool qk;
    void init()
    {
         memset(p,0,sizeof(p));
         for(int i=1;i<=n;i++)
         {
            scanf("%d%d",&a1,&a2);
            if(a1==1) p[12]++;
            if(a1==2) p[13]++;
            if(a1>2)  p[a1-2]++;
            if(!a1)
            {
               if(a2==1) p[14]++;
               if(a2==2) p[15]++;
            }
         }
    }
    void dfs(int st)
    {
            if(st>=jg) return;
            qk=1;
            int ss,sz,sf;
            ss=sz=sf=0;
            for(int i=1;i<=15;i++)
            {
              if(p[i]) qk=0;
              if(p[i]>=2) sz++;
              if(p[i]>=3) ss++;
              if(p[i]>=4) sf++;
            }
            if(qk)
            {
               jg=st;
               return;
            }
            if(st==jg-1) return;
            
            int temp;
            temp=0;
            for(int i=temp+1;i<=8;i++)
              if(p[i])
              {
                temp=i;
                for(int j=i+1;j<=12;j++)
                {
                  if(p[j]) temp=j;
                  else break;
                }
                if(temp>=i+4)
                {
                  for(int j=i;j<=temp;j++)  p[j]--;
                  st++;
                  dfs(st);
                  for(int j=i;j<=temp;j++)  p[j]++; 
                  st--;   
                }
                temp++;
              }
            if(sz>=3)
            {
               temp=0;
               for(int i=temp+1;i<=10;i++)
               if(p[i]>=2)
               {
                  temp=i;
                  for(int j=i+1;j<=12;j++)
                  {
                     if(p[j]>=2) temp=j;
                     else break;
                  }
                  if(temp>=i+2)
                  {
                    for(int j=i;j<=temp;j++)  p[j]-=2;
                    st++;
                    dfs(st);
                    for(int j=i;j<=temp;j++)  p[j]+=2;
                    st--;
                  }
                  if(temp-i+1==sz) break;
                  temp++;
               }
            }
            if(ss>=2)
            {
              temp=0;
              for(int i=temp+1;i<=11;i++)
                if(p[i]>=3)
                {
                   temp=i;
                   for(int j=i+1;j<=12;j++)
                   {
                      if(p[j]>=3) temp=j;
                      else break;
                   }
                   if(temp>=i+1)
                   {
                      for(int j=i;j<=temp;j++)  p[j]-=3;
                      st++;
                      dfs(st);
                      for(int j=i;j<=temp;j++)  p[j]+=3;
                      st--;
                   }
                   if(temp-i+1==ss) break;
                   temp++;
                }
            }
              
            if(sf)
              for(int i=1;i<=15;i++)
                if(p[i]>=4)
                {
                   p[i]-=4,st++;
                   for(int j=1;j<=15;j++)
                     if(p[j])
                     {
                        p[j]--;
                        for(int jk=j;jk<=15;jk++)
                          if(p[jk])
                          {
                             p[jk]--;
                             dfs(st);
                             p[jk]++;
                          }
                        p[j]++;
                     }
                   if(sz>=2)
                   {
                      for(int j=1;j<=15;j++)
                         if(p[j]>=2)
                         {
                            p[j]-=2;
                            for(int jk=j;jk<=15;jk++)
                               if(p[jk]>=2)
                               {
                                  p[jk]-=2;
                                  dfs(st);
                                  p[jk]+=2;
                               }
                            p[j]+=2;
                         }
                   }
                   p[i]+=4;
                   st--;
                   if(sf==1) break;
               }   
              
            if(ss)
              for(int i=1;i<=15;i++)
                if(p[i]>=3)
                {
                   p[i]-=3,st++;
                   for(int j=1;j<=15;j++)
                     if(p[j]&&j!=i)
                     {
                        p[j]--;
                        dfs(st);
                        p[j]++;
                     }
                   if(sz)
                     for(int j=1;j<=15;j++)
                       if(p[j]>=2)
                       {
                         p[j]-=2;
                         dfs(st);
                         p[j]+=2;
                       }
                   p[i]+=3,st--;
                   if(ss==1) break;
               }
            
            if(p[14]&&p[15])
            {
               p[14]--,p[15]--,st++;
               dfs(st);
               p[14]++,p[15]++,st--;
            }
            
            for(int i=1;i<=15;i++)
              if(p[i])
                st++;
            if(st<jg) jg=st;
    }
    int main()
    {
        scanf("%d%d",&t,&n);
        for(int l=1;l<=t;l++)
        {
           init();
           jg=0x3fff;
           dfs(0);
           printf("%d
    ",jg);
        }
        return 0;
    }
     
    landlords
  • 相关阅读:
    用场景来规划测试工作
    冲刺第二十天 到二十二天
    冲刺第十九天
    冲刺第十八天
    阅读《构建之法》第13-17章(包含读后感)
    冲刺第5,6天(5月25,26日)
    冲刺第四天(2天合一起当一篇随笔,明天会在这篇里继续更新)
    冲刺第二天
    作业5.2
    作业5.1
  • 原文地址:https://www.cnblogs.com/moyiii-/p/7260517.html
Copyright © 2011-2022 走看看