zoukankan      html  css  js  c++  java
  • [NOIP2015] 斗地主

    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

    solution

    一道大暴搜

        开始的时候没有想到应该按照什么样的顺序搜,弄得很没有头绪

       正解是想找长的搜,我是先找的各种顺子,然后是四个及带的,然后是三个及带的;最后是单牌,在搜的时候,要保证枚举到了各种情况,这样才能保证找到了最优解,所以用到了memcpy,枚举到了一种情况就继续搜索,在最后有一个极大的剪枝,当在排除掉所有枚举单牌的情况下,可以把剩下的手牌全部按相同的分次出掉,因为如果还有顺子之类的东西,在前面会枚举到,而且在最后扔的情况也不是最优解,这样就能省掉前面一段繁琐的枚举,能快很多;可以把2的编号与其他的隔开,这样无论如何也成不了顺子,省了很多事;

    感悟

    1、暴力搜索越早判断越好

    2、在搜的时候找准一种顺序全部枚举,可以先不考虑时间问题,可以在最后在集中想剪枝;

    3、memcpy超级有用,小数组都可以这么搞;

      1 #include<cmath>
      2 #include<queue>
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<iostream>
      7 #include<algorithm>
      8 using namespace std;
      9 int T,n,N,ans,lim;
     10 void find(int a[20],int num,int sum){
     11     if(num>ans) return ;
     12     if(sum==n){
     13         ans=num-1;
     14         return ;
     15     }
     16     int b[20],ji=1;
     17     if(n-sum>=6){
     18         for(int i=1;i<=lim;i++){
     19             if(a[i]<3){
     20                 ji=i+1; continue;
     21             }
     22             if(i-ji+1>=2){
     23                 memcpy(b,a,sizeof(b));
     24                 for(int j=ji;j<=i;j++){
     25                     b[j]-=3;
     26                 }
     27                 find(b,num+1,sum+3*(i-ji+1));
     28             }
     29         }
     30         ji=1;
     31         for(int i=1;i<=lim;i++){
     32             if(a[i]<2){
     33                 ji=i+1; continue;       
     34             }
     35             if(i-ji+1>=3){
     36                 memcpy(b,a,sizeof(b));
     37                 for(int j=ji;j<=i;j++){
     38                     b[j]-=2;
     39                 }
     40                 find(b,num+1,sum+2*(i-ji+1));
     41             }
     42         }
     43     }
     44     if(n-sum>=5){
     45         ji=1;
     46         for(int i=1;i<=lim;i++){
     47             if(a[i]<1){
     48                 ji=i+1; continue;   
     49             }
     50             if(i-ji+1>=5){
     51                 memcpy(b,a,sizeof(b));
     52                 for(int j=ji;j<=i;j++){
     53                     b[j]--;
     54                 }
     55                 find(b,num+1,sum+(i-ji+1));
     56             }
     57         }
     58     }
     59     int c[20];
     60     if(n-sum>=4){
     61         for(int i=1;i<=lim;i++){
     62             if(a[i]==4){
     63                 memcpy(b,a,sizeof(b));
     64                 b[i]-=4;
     65                 find(b,num+1,sum+4);
     66                 memcpy(b,a,sizeof(b));
     67                 b[i]-=4;
     68                 int mk, he=0;
     69                 if(n-sum-4>=4){
     70                     for(int j=1;j<=N;j++){
     71                         if(b[j]>=2){
     72                             if(b[j]==4){
     73                                 memcpy(c,b,sizeof(c));
     74                                 c[j]-=4;
     75                                 find(c,num+1,sum+8);
     76                             }
     77                             for(int k=j+1;k<=N;k++){
     78                                 if(b[k]>=2){
     79                                     memcpy(c,b,sizeof(c));
     80                                     c[j]-=2; c[k]-=2;
     81                                     find(c,num+1,sum+8);
     82                                 }
     83                             }
     84                         }
     85                     }
     86                 }
     87                 if(n-sum-2>=2){
     88                     for(int j=1;j<=N;j++){
     89                         if(b[j]>=1){
     90                             if(b[j]==2){
     91                                 memcpy(c,b,sizeof(c));
     92                                 c[j]-=2;
     93                                 find(c,num+1,sum+6);
     94                             }
     95                             for(int k=j+1;k<=N;k++){
     96                                 if(b[k]>=1){
     97                                     memcpy(c,b,sizeof(c));
     98                                     c[j]--; c[k]--;
     99                                     find(c,num+1,sum+6);
    100                                 }
    101                             }
    102                         }
    103                     }
    104                 }
    105                  
    106             }
    107         }
    108     }
    109     if(n-sum>=3){
    110         for(int i=1;i<=lim;i++){
    111             if(a[i]>=3){
    112                 memcpy(b,a,sizeof(b));
    113                 b[i]-=3;
    114                 find(b,num+1,sum+3);
    115                 memcpy(b,a,sizeof(b));
    116                 b[i]-=3;
    117                 if(n-sum-3>=2){
    118                     for(int j=1;j<=N;j++){
    119                         if(b[j]>=2){
    120                             memcpy(c,b,sizeof(c));
    121                             c[j]-=2;
    122                             find(c,num+1,sum+5);
    123                         }
    124                     }
    125                 }
    126                 if(n-sum-3>=1){
    127                     for(int j=1;j<=N;j++){
    128                         if(b[j]>=1){
    129                             memcpy(c,b,sizeof(c));
    130                             c[j]--;
    131                             find(c,num+1,sum+4);
    132                         }
    133                     }
    134                 }
    135             }
    136         }
    137     }
    138     int he=num-1;
    139     for(int i=1;i<=lim;i++){
    140         if(a[i]) he++; 
    141         if(he>=ans) return ;
    142     }
    143     ans=min(ans,he);
    144 }
    145 int main(){
    146     //freopen("a.in","r",stdin);
    147     //freopen("landlords.in","r",stdin);
    148     //freopen("landlords.out","w",stdout);
    149     scanf("%d%d",&T,&n);
    150     int a[20];
    151     N=14; lim=18;
    152     while(T--){
    153         memset(a,0,sizeof(a));
    154         int x,y;
    155         for(int i=1;i<=n;i++){
    156             scanf("%d%d",&x,&y);
    157             if(x==1) a[14]++;
    158             else if( x==2 ) a[16]++;
    159             else if(x==0 && y==1) a[17]++;
    160             else if(x==0 && y==2) a[17]++;
    161             else a[x]++;
    162         }
    163         ans=0x7fffffff;
    164         find(a,1,0);
    165         printf("%d
    ",ans);
    166     }
    167     return 0;
    168 }
     
  • 相关阅读:
    CCI_Q1.5
    CCI_Q1.4
    js 记录一次日期转换
    列表注册自定义鼠标右键事件
    jquery点击页面其他位置隐藏div
    C#一句话判断两个List<T>是否相等
    使用Js进行linq处理
    记录一次DataTable排序的问题
    JavaScript模板引擎Handlebars
    Redis学习笔记
  • 原文地址:https://www.cnblogs.com/FOXYY/p/7265713.html
Copyright © 2011-2022 走看看