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;
    }
    
  • 相关阅读:
    Legendary Items-微软2017实习生笔试第一题
    (转载)华为离职副总裁徐家骏:年薪千万的工作感悟
    【AtCoder Regular Contest 092】C.2D Plane 2N Points【匈牙利算法】
    poj 2236【并查集】
    poj 2431 【优先队列】
    poj 3280【区间dp】
    uva 10453 【回文串区间dp】
    uva 10739【基础(区间)dp】
    poj 2385【动态规划】
    poj 2229 【完全背包dp】【递推dp】
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7638254.html
Copyright © 2011-2022 走看看