[NOIP2015]斗地主

题意:给你一副牌,按照它的规则出牌,求最小出完次数。

dfs大法好!!!

#include<cstdio>

int T,n,ans=30;
int p[20];//0 3~13 15 16
bool check()
{
    if(p[0])return 0;
    for(int i=3;i<=16;i++)if(p[i])return 0;
    return 1;
}
void dfs(int dep)
{
    if(check())
    {
        ans=ans<dep?ans:dep;
        return ;
    }
    if(dep>ans)return ;
    int tp = 0;
    for(int i=0;i<=16;i++)
    {
        if(p[i])
        {
            tp = i;
            break;
        }
    }
    if(p[tp]>=2)
    {
        p[tp]-=2;
        for(int i=tp;i<=16;i++)
        {
            if(p[i]>=3)
            {
                if(p[i]>=4)
                {
                    p[i]-=4;
                    dfs(dep+1);
                    if(tp)
                    {
                        for(int j=tp;j<=15;j++)
                        {
                            if(p[j]>=2)
                            {
                                p[j]-=2;
                                dfs(dep+1);
                                p[j]+=2;
                            }
                        }
                    }
                    p[i]+=4;
                }
                p[i]-=3;
                dfs(dep+1);
                p[i]+=3;
            }
        }
        p[tp]+=2;
    }
    p[tp]--;
    for(int i=tp+1;i<=16;i++)
    {
        if(p[i]>=3)
        {
            p[i]-=3;
            dfs(dep+1);
            p[i]+=3;
            if(p[i]>=4)
            {
                p[i]-=4;
                for(int j=tp;j<=16;j++)
                {
                    if(p[j])
                    {
                        p[j]--;
                        dfs(dep+1);
                        p[j]++;
                    }
                }
                p[i]+=4;
            }
        }
    }
    p[tp]++;
    if(!tp)
    {
        for(int i=2;i<=16;i++)
        {
            if(p[i]==4)
            {
                p[i]-=4;
                p[0]--;
                for(int j=0;j<=16;j++)
                {
                    if(p[j])
                    {
                        p[j]--;
                        dfs(dep+1);
                        p[j]++;
                    }
                }
                p[i]+=4;
                p[0]++;
            }else if(p[i]==3)
            {
                p[i]-=3;
                if(p[0]>1)
                {
                    p[0]-=2;
                    dfs(dep+1);
                    p[0]+=2;
                    p[0]--;
                    dfs(dep+1);
                    p[0]++;
                }else
                {
                    p[0]--;
                    dfs(dep+1);
                    p[0]++;
                }
                p[i]+=3;
            }
        }
        if(p[tp]==2)
        {
            p[tp]-=2;
            dfs(dep+1);
            p[tp]+=2;
        }
        p[tp]--;
        dfs(dep+1);
        p[tp]++;
    }else
    {
        if(p[tp]>=3)
        {
            int to = tp;
            while(p[to]>=3)
            {
                p[to]-=3;
                to++;
            }
            to--;
            for(int i=to;i>=tp;i--)
            {
                dfs(dep+1);
                p[i]+=3;
            }
            p[tp]-=3;
            for(to = tp;to<=16;to++)
            {
                if(p[to])
                {
                    if(p[to]>=2)
                    {
                        p[to]-=2;
                        dfs(dep+1);
                        p[to]+=2;
                    }
                    p[to]--;
                    dfs(dep+1);
                    p[to]++;
                }
            }
            p[tp]+=3;
            if(p[tp]>=4)
            {
                p[tp]-=4;
                for(int to1 = tp;to1<=16;to1++)
                {
                    if(p[to1])
                    {
                        p[to1]--;
                        for(int to2 = to1;to2<=16;to2++)
                        {
                            if(p[to2])
                            {
                                p[to2]--;
                                dfs(dep+1);
                                p[to2]++;
                            }
                        }
                        p[to1]++;
                    }
                }
                dfs(dep+1);
                p[tp]+=4;
            }
        }
        int to = tp;
        if(p[tp]>=2)
        {
            to =  tp;
            while(p[to]>=2)
            {
                p[to++]-=2;
            }
            to--;
            while(to>=tp)
            {
                if(to-tp+1>=3)dfs(dep+1);
                p[to--]+=2;
            }
            p[tp]-=2;
            dfs(dep+1);
            p[tp]+=2;
        }
        to = tp;
        while(p[to])
        {
            p[to++]--;
        }
        to--;
        while(to>=tp)
        {
            if(to-tp+1>=5)dfs(dep+1);
            p[to--]++;
        }
        p[tp]--;
        dfs(dep+1);
        p[tp]++;
    }
}
int main()
{
    scanf("%d%d",&T,&n);
    while(T--)
    {
        for(int i=0;i<=16;i++)p[i]=0;
        ans=30;
        for(int num,c,i=1;i<=n;i++)
        {
            scanf("%d%d",&num,&c);
            if(num==1)num=14;
            if(num==2)num=16;
            p[num]++;
        }
        dfs(0);
        printf("%d\n",ans);
    }
    return 0;
}

源文件, 语言: C++

猜你喜欢

转载自www.cnblogs.com/LiGuanlin1124/p/9582152.html
今日推荐