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

    题意:给你一手牌,要你按照斗地主的规则以最少的出牌次数把这手牌打完传送门

    题解:

    搜索

    搜索顺子,然后开桶打光散牌,记录最小答案即可

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #define ll long long 
    using namespace std;
    
    int gi() {
      char ch=getchar(); int x=0;
      while(ch<'0' || ch>'9') ch=getchar();
      while(ch>='0' && ch<='9') {x=10*x+ch-'0';ch=getchar();}
      return x;
    }
    
    int T,n,ans;
    int num[10],cnt[20];
    
    int others() {
      int tot=0;
      memset(num,0,sizeof(num));
      for(int i=1; i<=14; i++) num[cnt[i]]++;
      while(num[4] && num[2]>=2) tot++,num[4]--,num[2]-=2;
      while(num[4] && num[1]>=2) tot++,num[4]--,num[1]-=2;
      while(num[4] && num[2]>=1) tot++,num[4]--,num[2]--;
      while(num[3] && num[2]>=1) tot++,num[3]--,num[2]--;
      while(num[3] && num[1]>=1) tot++,num[3]--,num[1]--;
      return tot+num[1]+num[2]+num[3]+num[4];
    }
    
    void dfs(int k) {
      if(k>=ans) return;
      ans=min(ans,others()+k);//在当前出牌阶段强行把牌打光的次数  
      for(int i=3; i<=13; i++) {
        if(cnt[i]>=3) {
          int j=i;
          while(cnt[j]>=3 && j<=14) j++;
          if(j-i>=2) {
            for(int l=i+1; l<j; l++) {
              for(int p=i; p<=l; p++) cnt[p]-=3;
              dfs(k+1);
              for(int p=i; p<=l; p++) cnt[p]+=3;
            }
          }
        }
      }
      for(int i=3; i<=12; i++) {
        if(cnt[i]>=2) {
          int j=i;
          while(cnt[j]>=2 && j<=14) j++;
          if(j-i>=3) {
            for(int l=i+2; l<j; l++) {
              for(int p=i; p<=l; p++) cnt[p]-=2;
              dfs(k+1);
              for(int p=i; p<=l; p++) cnt[p]+=2;
            }
          }
        }
      }
      for(int i=3; i<=10; i++) {
        if(cnt[i]>=1) {
          int j=i;
          while(cnt[j]>=1 && j<=14) j++;
          if(j-i>=5) {
            for(int l=i+4; l<j; l++) {
              for(int p=i; p<=l; p++) cnt[p]--;
              dfs(k+1);
              for(int p=i; p<=l; p++) cnt[p]++;
            }
          }
        }
      }
    }
    
    int main() {
      T=gi(),n=gi();
      while(T--) {
        ans=1<<30;
        memset(cnt,0,sizeof(cnt));
        for(int i=1; i<=n; i++) {
          int numb=gi(),col=gi();
          if(numb==1) numb=14;//A变成14
          if(numb==0) numb=1;//大小王变成1
          cnt[numb]++;
        }
        dfs(0);
        printf("%d
    ", ans);
      }
      return 0;
    }
    
  • 相关阅读:
    table拖动列宽
    解决 wm_concat函数 长度不够问题
    「Luogu」[JSOI2007]字符加密 解题报告
    Markdown数学符号
    「P5004」专心OI
    「CF242E」XOR on Segment 解题报告
    「CF86D」Powerful array 解题报告
    「USACO08JAN」电话线Telephone Lines 解题报告
    「Luogu P2015」二叉苹果树 解题报告
    「Luogu P3866」[TJOI2009]战争游戏 解题报告
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7638254.html
Copyright © 2011-2022 走看看