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 组手牌的最少次数。

    solution

    真是宇宙无敌大暴搜............(ps:反正我是对着测试点一个一个改过来的........)

    不应该是状压:wxh和wq神犇都用状压,反正没改出来

    牌型只有三种:1.顺子 2.带牌 3.单牌/对牌  (火箭也算对牌)

    1.出牌的顺序不会影响答案

    2.先搜顺子可以剪更多的枝,而且搜完顺子后,带牌和 单牌/对牌 可以用贪心求出

    思路:

    先 暴搜顺子  枚举  单/双/三顺子  左端点  右端点

    之后用贪心求 其他牌型  (情况可能会很多.......)

    我说说我遇到的坑点:

    1.A可以当顺子

    2.有不出顺子的出牌方式

    3.4个2可以带2个王

    4.注意贪心时 判断的优先级

    5.4张牌 可以带两个相同的 单/对牌  例如:4个3 带4个2/带对2

    这真是一个好题,不能浪费啊..

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #include<vector>
      5 #define ll long long
      6 #define mem(a,b) memset(a,b,sizeof(a))
      7 using namespace std;
      8 inline int minn(int a,int b){return a<b?a:b;}
      9 
     10 int t,n;
     11 int u,o,bushu;
     12 int a[15];
     13 int limit[4]={0,5,3,2};
     14 
     15 void clear()
     16 {
     17     mem(a,0);
     18 }
     19 
     20 bool check(int l,int size)
     21 {
     22     if(l+limit[size]-1>13)return 0;
     23     for(int i=l+limit[size]-1;i>=l;--i)
     24       if(a[i]<size)return 0;
     25     return 1;
     26 }
     27 
     28 void dfs(int now)
     29 {
     30     for(int size=1;size<=3;++size)
     31         for(int l=2;l<=13;++l)
     32         {
     33             if(!a[l])continue;
     34             if(!check(l,size))continue;
     35             for(int r=l+limit[size]-1;r<=13;++r)
     36             {
     37                 if(a[r]<size)break;
     38                 for(int k=l;k<=r;++k)
     39                   a[k]-=size;
     40                 dfs(now+1);
     41                 for(int k=l;k<=r;++k)
     42                   a[k]+=size;
     43             }
     44         }
     45     
     46     int temp[15];
     47     memcpy(temp,a,sizeof(temp));
     48     
     49     int num1=0,num2=0,num3=0,num4=0;
     50     for(int i=1;i<=13;++i)
     51     {
     52         if(temp[i]==1)++num1;
     53         else if(temp[i]==2)++num2;
     54         else if(temp[i]==3)++num3;
     55         else if(temp[i]==4)++num4;
     56     }
     57     if(num4)
     58       while(num4)
     59       {
     60             if(num1>=2){num1-=2;++now;--num4;continue;}
     61           if(num1==1)
     62           {
     63                 if(num2>=2){num2-=2;--num4;++now;continue;}
     64                 if(temp[14]){--num1;--temp[14];--num4;++now;continue;}
     65                 if(num2){--num2;--num4;++now;continue;}
     66             }
     67             if(num1==0)
     68             {
     69                 if(num2>=2){num2-=2;--num4;++now;continue;}
     70                 if(temp[14]==2){temp[14]=0;--num4;++now;continue;}
     71                 if(temp[14]==1)
     72                     if(num2){--temp[14];--num2;++num1;--num4;++now;continue;}
     73             }
     74             break;
     75         }
     76     if(num3)
     77       while(num3)
     78       {
     79             if(num1){--num1;--num3;++now;continue;}
     80             if(temp[14]){--temp[14];--num3;++now;continue;}
     81             if(num2){--num2;--num3;++now;continue;}
     82             break;
     83         }
     84     
     85     if(temp[14]==2){temp[14]=0;++now;}
     86     int qw=0;
     87     if(num4>=2)
     88         while(num4>=2){num4-=2;++qw;}//4带两个相同的对 
     89     
     90     bushu=minn(now+num1+num2+num3+num4+temp[14]+qw,bushu);
     91 }
     92 
     93 int main(){
     94     scanf("%d%d",&t,&n);
     95     while(t--)
     96     {
     97         clear();
     98         for(int i=1;i<=n;++i)
     99         {
    100             scanf("%d%d",&u,&o);
    101             if(!u)++a[14];
    102             else
    103               if(u==1)
    104                 ++a[13];
    105             else
    106               ++a[u-1];
    107         }
    108         bushu=0x7fffffff;
    109         dfs(0);
    110         printf("%d
    ",bushu);
    111     }
    112     //while(1);
    113     return 0;
    114 }
    code
  • 相关阅读:
    人机猜拳
    M1分数分配
    postmortem report of period M1
    视频文档分享网站场景测试说明书
    功能规格说明书
    11.9Daily Scrum
    11.6Daily Scrum
    需求博客
    11.5Daily Scrum
    11.3Daily Scrum
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7260032.html
Copyright © 2011-2022 走看看