NOIP2015 斗地主

Sol

暴力搜索...不用搜1,2张的情况,直接统计出来就可以了.

还有处理一下2和大王小王的位置,扔到最后面或者最前面就可以了.

搜索就搜 3+3,2+2+2,1+1+1+1+1 这三个就可以了.

Code

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
 
const int N = 25;
 
int T,n,ans;
int t[]={13,11,12,0,1,2,3,4,5,6,7,8,9,10};
int a[N];
 
inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
 
void DFS(int d){
    if(d>ans) return;
    int c[5]={0,0,0,0,0};
    for(int i=0;i<=13;i++) if(a[i]==1) c[1]++;
    for(int i=0;i<=13;i++) if(a[i]==2) c[2]++;
    for(int i=0;i<=13;i++) if(a[i]==3){
        c[3]++;
        if(c[2]>=1) c[2]--;else if(c[1]>=1) c[1]--;
    }
    for(int i=0;i<=13;i++) if(a[i]==4){
        c[4]++;
        if(c[1]>=2) c[1]-=2;else if(c[2]>=2) c[2]-=2;else if(c[2]>=1) c[2]--;
    }
     
    ans=min(ans,d+c[1]+c[2]+c[3]+c[4]);
     
    //3+3
    for(int i=0,j;i<=10;i++){
        for(j=i;j<=11;j++){
            a[j]-=3;
            if(a[j]<0) break;
            if(j-i+1>=2) DFS(d+1);
        }if(j==12) j--;
        while(j>=i) a[j--]+=3;
    }
    //2+2+2
    for(int i=0,j;i<=9;i++){
        for(j=i;j<=11;j++){
            a[j]-=2;
            if(a[j]<0) break;
            if(j-i+1>=3) DFS(d+1);
        }if(j==12) j--;
        while(j>=i) a[j--]+=2;
    }
    //1+1+1+1+1
    for(int i=0,j;i<=7;i++){
        for(j=i;j<=11;j++){
            a[j]--;
            if(a[j]<0) break;
            if(j-i+1>=5) DFS(d+1);
        }if(j==12) j--;
        while(j>=i) a[j--]++;
    }
}
 
int main(){
    for(T=in(),n=in();T--;){
        ans=n;memset(a,0,sizeof(a));
        for(int i=1,u,v;i<=n;i++) u=in(),v=in(),a[t[u]]++;
        DFS(0);
        printf("%d\n",ans);
    }return 0;
}

  

posted @ 2016-09-24 09:23  北北北北屿  阅读(280)  评论(0编辑  收藏  举报