• [NOIP2015]斗地主


    2106. [NOIP2015] 斗地主

    ★★★☆   输入文件:landlords.in   输出文件:landlords.out   简单对比
    时间限制:2 s   内存限制:1025 MB

    牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。

    现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。

    需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。

    具体规则如下:

    【输入格式】

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

    接下来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的规模如下:

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

      恩,这一定是一个伪的斗地主。我们看题目描述:发现确实没什么好的方法,而且数据范围又比较小,肯定是DFS无疑了,(但是为什么内存辣么大,吓坏我了( ⊙ o ⊙ )!)

    这道题就没啦,因为dfs的层数会很多,所以一定要剪枝,减的越早越好!

      (听说那些大佬们都拿数组传参打的,但是一个没有回溯的dfs不是一个好的dfs!);

    附代码:

      

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int N=14;
      7 void dfs(int,int);
      8 int read(){
      9     int sum=0;char ch=getchar();
     10     while(ch<'0'||ch>'9') ch=getchar();
     11     while(ch>='0'&&ch<='9') {sum=sum*10+ch-'0';ch=getchar();}
     12     return sum;
     13 }
     14 inline int min(int x,int y){return x<y?x:y;}
     15 int T,n,x,y;
     16 int a[20],ans;
     17 void three(int cnt,int sum){
     18     for(int i=3;i<=N-1;++i){
     19         if(a[i]>=3&&a[i+1]>=3){
     20             a[i]-=3;int j;
     21             for(j=i+1;j;++j){
     22                 if(a[j]>=3){
     23                     a[j]-=3;
     24                     dfs(cnt+1,sum+3*(j-i+1));
     25                 }
     26                 else 
     27                     break;    
     28             }
     29             for(j=j-1;j>i;j--){
     30             //    dfs(cnt+1,sum+3*(j-i+1));
     31                 a[j]+=3;
     32             }
     33             a[i]+=3;
     34         }
     35     }
     36 }
     37 void two(int cnt,int sum){
     38     for(int i=3;i<=N-2;++i){
     39         if(a[i]>=2&&a[i+1]>=2&&a[i+2]>=2){
     40             a[i]-=2;a[i+1]-=2;int j;
     41             for(j=i+2;j;++j){
     42                 if(a[j]>=2){
     43                     a[j]-=2;
     44                     dfs(cnt+1,sum+2*(j-i+1));
     45                 }
     46                 else 
     47                     break;    
     48             }
     49             for(j=j-1;j>=i+2;j--){
     50                 a[j]+=2;
     51             }
     52             a[i]+=2;a[i+1]+=2;
     53         }
     54     }
     55 }
     56 void one(int cnt,int sum){
     57     for(int i=3;i<=N-4;++i){
     58         if(a[i]&&a[i+1]&&a[i+2]&&a[i+3]&&a[i+4]){
     59             a[i]--;a[i+1]--;a[i+2]--;a[i+3]--;int j;
     60             for(j=i+4;;++j){
     61                 if(a[j]){
     62                     a[j]--;
     63                     dfs(cnt+1,sum+j-i+1);
     64                 }
     65                 else 
     66                     break;    
     67             }
     68             for(j=j-1;j>=i+4;j--){
     69                 //dfs(cnt+1,sum+j-i+1);
     70                 a[j]++;
     71             }
     72             a[i]++;a[i+1]++;a[i+2]++;a[i+3]++;
     73         }
     74     }    
     75 }
     76 void four_two(int cnt,int sum){
     77     for(int i=2;i<=N;++i)
     78         if(a[i]==4){
     79             a[i]=0;
     80             for(int j=0;j<=N;++j)
     81                 for(int u=j+1;u<=N;++u){
     82                     if(a[j]==2&&a[u]==2){
     83                         a[j]=0;a[u]=0;
     84                         dfs(cnt+1,sum+8);
     85                         a[j]=2;a[u]=2;
     86                     }        
     87                 }
     88             a[i]=4;
     89         }
     90 }
     91 void four_twos(int cnt,int sum){
     92     for(int i=1;i<=N;++i)
     93         if(a[i]==4){
     94             a[i]=0;
     95             for(int j=0;j<=N;++j)
     96                 for(int u=j+1;u<=N;++u){
     97                     if(a[j]==1&&a[u]==1){
     98                         a[j]=0;a[u]=0;
     99                         dfs(cnt+1,sum+6);
    100                         a[j]=1;a[u]=1;
    101                     }
    102                 }
    103             a[i]=4;
    104         }
    105 }
    106 void three_two(int cnt,int sum){
    107     for(int i=1;i<=N;++i)
    108         if(a[i]==3){
    109             a[i]=0;
    110             for(int j=1;j<=N;++j)
    111                 if(a[j]==2){
    112                     a[j]=0;
    113                     dfs(cnt+1,sum+5);
    114                     a[j]=2;
    115                 }    
    116             a[i]=3;
    117         }
    118 }
    119 void three_one(int cnt,int sum){
    120     for(int i=1;i<=N;++i)
    121         if(a[i]==3){
    122             a[i]=0;
    123             for(int j=1;j<=N;++j)
    124                 if(a[j]){
    125                     a[j]--;  
    126                     dfs(cnt+1,sum+4);
    127                     a[j]++;  
    128                 }    
    129             a[i]=3;
    130         }
    131 }
    132 void third(int cnt,int sum){
    133     for(int i=1;i<=N;++i)
    134         if(a[i]==3){
    135             a[i]=0;
    136             dfs(cnt+1,sum+3);
    137             a[i]=3;
    138         }
    139 }
    140 void second(int cnt,int sum){
    141     for(int i=1;i<=N;++i)
    142         if(a[i]==2){
    143             a[i]-=2;
    144             dfs(cnt+1,sum+2);
    145             a[i]+=2;
    146         }
    147 }
    148 void dfs(int cnt,int sum){
    149     int pp=n-sum;
    150     if(cnt>=ans) return;
    151     if(pp>=6)    three(cnt,sum);
    152     if(pp>=6)    two(cnt,sum);
    153     if(pp>=5)    one(cnt,sum);
    154     if(pp>=8)    four_two(cnt,sum);
    155     if(pp>=6)    four_twos(cnt,sum);
    156     if(pp>=5)    three_two(cnt,sum);
    157     if(pp>=4)    three_one(cnt,sum);
    158     if(pp>=3)    third(cnt,sum); 
    159     int zz=sum;
    160     for(int i=1;i<=N;++i)
    161         if(a[i]==2)
    162             zz++;
    163     ans=min(ans,cnt+n-zz);
    164         
    165 }
    166 int main(){
    167     freopen("landlords.in","r",stdin);
    168     freopen("landlords.out","w",stdout);
    169     T=read();n=read();
    170     while(T--){
    171         ans=0x7fffffff;
    172         memset(a,0,sizeof(a));
    173         for(int i=1;i<=n;++i){
    174             x=read();y=read();
    175             if(x==1) a[14]++;    
    176             else if(!x) a[1]++;
    177             else a[x]++;
    178         }
    179         dfs(0,0);
    180         printf("%d
    ",ans);
    181     }
    182     return 0;
    183 }
  • 相关阅读:
    117. Populating Next Right Pointers in Each Node II
    50. Pow(x, n)
    494. Target Sum
    Word Ladder
    HDU 4417
    POJ 2104
    POJ 3277
    【转】图论500题
    POJ 2991
    POJ 1436
  • 原文地址:https://www.cnblogs.com/Maplers/p/7260153.html
Copyright © 2020-2023  润新知