zoukankan      html  css  js  c++  java
  • [BZOJ 4325][NOIP 2015] 斗地主

    一道防AK好题

    4325: NOIP2015 斗地主

    Time Limit: 30 Sec  Memory Limit: 1024 MB
    Submit: 820  Solved: 560
    [Submit][Status][Discuss]

    Description

     牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。具体规则如下:

    Input

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

    接下来T组数据,每组数据N行,每行一个非负整数对Ai,Bi,表示一张牌,其中Ai表示牌的数码,Bi表示牌的花色,中间用空格隔开。特别的,我们用1来表示数码A,11表示数码J,12表示数码Q,13表示数码K;黑桃、红心、梅花、方片分别用1-4来表示;小王的表示方法为01,大王的表示方法为02。
     

    Output

    共T行,每行一个整数,表示打光第T组手牌的最少次数。

    Sample Input

    1 8
    7 4
    8 4
    9 1
    10 4
    11 1
    5 1
    1 4
    1 1

    Sample Output

    3

    HINT

     共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方


    片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张

    牌(黑桃5)以及对子牌(黑桃A以及方片A)在3次内打光。

     

    T<=10

    N<=23

    港真估计只有真正的$dalao$才能在考场上思路明确地码完这题qwq

    虽然实际写出来代码量倒也不算大,比某维修数列好到不知哪里去了

    这种大模拟的马力出题人应该被挂起来裱(雾)

    正解就是个大暴搜,$DFS$查找顺牌的同时扫描查找带牌...

    查找带牌时遵循尽量出最多的牌的贪心策略即可w

    需要注意的是王牌可以出现在带牌里(四个 2 带俩王2333333)但是王牌和2都不能出现在顺子里

    其他的完全乱搞就行只要能保证正确性w

    参考做法

    GitHub

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <iostream>
      5 #include <algorithm>
      6 
      7 int n;
      8 int ans;
      9 int sum[20];
     10 int cnt[10];
     11 
     12 int MakePair();
     13 void DFS(int);
     14 void Initialize();
     15 int Convert(int);
     16 
     17 int main(){
     18     int t;
     19     scanf("%d%d",&t,&n);
     20     while(t--){
     21         Initialize();
     22         ans=MakePair();
     23         DFS(0);
     24         printf("%d
    ",ans);
     25     }
     26 }
     27 
     28 void Initialize(){
     29     int x,trash;
     30     memset(sum,0,sizeof(sum));
     31     for(int i=0;i<n;i++){
     32         scanf("%d%d",&x,&trash);
     33         sum[Convert(x)]++;
     34     }
     35 }
     36 
     37 int MakePair(){
     38     memset(cnt,0,sizeof(cnt));
     39     int ans=0;
     40     for(int i=1;i<=14;i++)
     41         cnt[sum[i]]++;
     42     while(cnt[4]>=1&&cnt[2]>=2){
     43         cnt[4]--;
     44         cnt[2]-=2;
     45         ans++;
     46     }
     47     while(cnt[4]>=1&&cnt[1]>=2){
     48         cnt[4]--;
     49         cnt[1]-=2;
     50         ans++;
     51     }
     52     while(cnt[3]>=1&&cnt[2]>=1){
     53         cnt[3]--;
     54         cnt[2]--;
     55         ans++;
     56     }
     57     while(cnt[3]>=1&&cnt[1]>=1){
     58         cnt[3]--;
     59         cnt[1]--;
     60         ans++;
     61     }
     62     ans+=cnt[1]+cnt[2]+cnt[3]+cnt[4];
     63     return ans;
     64 }
     65 
     66 void DFS(int deep){
     67     if(deep>ans)
     68         return;
     69     ans=std::min(ans,deep+MakePair());
     70     for(int i=1;i<=11;i++){
     71         int tmp=i;
     72         while(tmp<=12&&sum[tmp]>=3)
     73             tmp++;
     74         tmp--;
     75         if(tmp-i+1<2)
     76             continue;
     77         for(int k=tmp;k-i+1>=2;k--){
     78             for(int j=i;j<=k;j++)
     79                 sum[j]-=3;
     80             DFS(deep+1);
     81             for(int j=i;j<=k;j++)
     82                 sum[j]+=3;
     83         }
     84     }
     85     for(int i=1;i<=10;i++){
     86         int tmp=i;
     87         while(tmp<=12&&sum[tmp]>=2)
     88             tmp++;
     89         tmp--;
     90         if(tmp-i+1<3)
     91             continue;
     92         for(int k=tmp;k-i+1>=3;k--){
     93             for(int j=i;j<=k;j++)
     94                 sum[j]-=2;
     95             DFS(deep+1);
     96             for(int j=i;j<=k;j++)
     97                 sum[j]+=2;
     98         }
     99     }
    100     for(int i=1;i<=8;i++){
    101         int tmp=i;
    102         while(tmp<=12&&sum[tmp]>=1)
    103             tmp++;
    104         tmp--;
    105         if(tmp-i+1<5)
    106             continue;
    107         for(int k=tmp;k-i+1>=5;k--){
    108             for(int j=i;j<=k;j++)
    109                 sum[j]--;
    110             DFS(deep+1);
    111             for(int j=i;j<=k;j++)
    112                 sum[j]++;
    113         }
    114     }
    115 }
    116 
    117 inline int Convert(int x){
    118     if(x==0)
    119         return 14;
    120     else if(x==2)
    121         return 13;
    122     else if(x==1)
    123         return 12;
    124     else
    125         return x-2;
    126 }
    Backup

  • 相关阅读:
    项目打包文件build.xml
    【转】常见面试之机器学习算法思想简单梳理
    【转】11位机器学习大牛最爱算法全解
    Simplify Path
    Text Justification
    Valid Number
    Substring with Concatenation of All Words
    Shortest Palindrome
    Palindrome Pairs
    Decode Ways
  • 原文地址:https://www.cnblogs.com/rvalue/p/7260344.html
Copyright © 2011-2022 走看看