noip大搜索 斗地主

各种贪心,玄学剪枝

1.先出顺子,毕竟你可以先出五张牌以上呢

2.然后,四带与三带

最后,剩下各种单,由于数据绝对合法,无论是一张,两张,还是三张,四张都可以一次性出完。

#include
#define re return
#define st static
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i)

templateinline void read(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')c=getchar();
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

using namespace std;
int a[20],t,n,ans;

void doudizhu(int x)
{
    if(x>ans)re;
    
    int k=0; 
    inc(i,3,14)//单顺子 
    if(!a[i])k=0;
    else
    {
        k++;
        if(k>=5)
        {
            inc(j,0,k-1)a[i-j]--;
            doudizhu(x+1);
            inc(j,0,k-1)a[i-j]++;	
        }	
    }
    
    k=0;
    inc(i,3,14)//双顺子
    if(a[i]<=1)k=0; 
    else 
    {
        k++;
        if(k>=3)
        {
            inc(j,0,k-1)a[i-j]-=2;
            doudizhu(x+1);
            inc(j,0,k-1)a[i-j]+=2;
        }
    }
    
    k=0;
    inc(i,3,14)//三顺子
    if(a[i]<=2)k=0; 
    else 
    {
        k++;
        if(k>=2)
        {
            inc(j,0,k-1)a[i-j]-=3;
            doudizhu(x+1);
            inc(j,0,k-1)a[i-j]+=3;
        }
    }
//------------------------------------------------------------------------------------------------------------------------------

    inc(i,2,14)
    {
        if(a[i]==4)//四带 
        {
            a[i]-=4;    
            
        
            inc(j,2,14)
            if(a[j]>=2)
            {
                a[j]-=2;
                inc(z,2,14)
                {
                    if(a[z]>=2)
                    {
                        a[z]-=2;
                        doudizhu(x+1);
                        a[z]+=2;
                    }
                }
                a[j]+=2;
            }
            
                  
           inc(j,2,15)   //四带二 
           {
           	if(!a[j])continue;
               a[j]--;
               inc(z,2,15)
               if(a[z])
               {
               	a[z]--;
               	doudizhu(x+1);
               	a[z]++;
               }
               a[j]++;	
           } 
            
            doudizhu(x+1);
            a[i]+=4;
        }
        if(a[i]>=3)//三带 
        {
            a[i]-=3;
            inc(j,2,14)
            if(a[j]>=2)//三带二 
            {
            a[j]-=2;	
            doudizhu(x+1);
            a[j]+=2;	
            }
        
            inc(j,2,15)
            if(a[j]&&j!=i)//三带一 
            {
                a[j]--;
                doudizhu(x+1);
                a[j]++;
            }
            doudizhu(x+1);
            a[i]+=3;
        }
    }	
//------------------------------------------------------------------------------------------------------------------------
    inc(i,2,15)if(a[i])x++;
    ans=min(ans,x);
}


void vcc()
{
    int x,y;
    ans=23;
    memset(a,0,sizeof(a));
    inc(i,1,n)
    {
        read(x),read(y);
        if(!x)a[15]++;
        else if(x==1)a[14]++;
        else a[x]++;
    }
    doudizhu(0);
    printf("%d\n",ans);
}
int main()
{
    read(t),read(n);
    while(t--)vcc();
    re 0;
}

你可能感兴趣的:(noip)