noip 2015 斗地主 大爆搜!!!

反正肯定是大模拟

但是每一个可以出的牌都搜一定不是最优的

考虑最特殊的出牌方案:顺子(单,对,三)

每一种方案再加上暴力贪心打出剩下的牌的步数

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#define N 35
using namespace std;
int a[N],num[N],n,T,ANS;
void read(){
    int x,nouse;
    memset(a,0,sizeof a);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&x,&nouse);
        if(x==1) a[12]++; if(x==2) a[13]++;
        if(x==0) a[14]++; if(x>=3) a[x-2]++;
    }
}
int no_str(){
    memset(num,0,sizeof num); int tot=0;
    for(int i=1;i<=14;i++) num[a[i]]++;
    while(num[4]&&num[2]>=2)num[4]--,num[2]-=2,tot++;
    while(num[4]&&num[1]>=2)num[4]--,num[1]-=2,tot++;
    while(num[3]&&num[2])num[3]--,num[2]--,tot++;
    while(num[3]&&num[1])num[3]--,num[1]--,tot++;
    return tot+num[1]+num[2]+num[3]+num[4];
}
void dfs(int step){
    if(step>ANS) return;
    ANS=min(ANS,step+no_str());
    for(int i=1;i<=11;i++){
        int ii=i;
        while(ii<=12&&a[ii]>=3)ii++;ii--;
        if(ii-i+1<2) continue;
        for(;ii-i+1>=2;ii--){
            for(int j=i;j<=ii;j++) a[j]-=3;
            dfs(step+1);
            for(int j=i;j<=ii;j++) a[j]+=3;
        }
    }
    for(int i=1;i<=10;i++){
        int ii=i;
        while(ii<=12&&a[ii]>=2)ii++;ii--;
        if(ii-i+1<3) continue;
        for(;ii-i+1>=3;ii--){
            for(int j=i;j<=ii;j++) a[j]-=2;
            dfs(step+1);
            for(int j=i;j<=ii;j++) a[j]+=2;
        }
    }
    for(int i=1;i<=8;i++){
        int ii=i;
        while(ii<=12&&a[ii])ii++;ii--;
        if(ii-i+1<5) continue;
        for(;ii-i+1>=5;ii--){
            for(int j=i;j<=ii;j++) a[j]--;
            dfs(step+1);
            for(int j=i;j<=ii;j++) a[j]++;
        }
    }
}
int main()
{
    //freopen("landlords.in","r",stdin);
    //freopen("landlords.out","w",stdout);
    scanf("%d%d",&T,&n);
    while(T--){
        read();
        ANS=no_str();
        dfs(0);
        printf("%d
",ANS);
    }
}


原文地址:https://www.cnblogs.com/Ren-Ivan/p/7746726.html