首页 > 代码库 > 7.30考试(第一发博文)

7.30考试(第一发博文)

  第一篇博文献给NOIP2015斗地主。

  这道题为NOIP2015第一天第三题。属于爆搜类,没有任何算法,就是模拟加爆搜。由于有不同种打法,dfs分为好几层,本着先大后小便于剪枝的原则,先出顺子,再带牌,最后散着出。

  首先,花色对结果无影响,其次大小王对结果是否有贡献只看是否出现其中之一,出现结果+1即可,未出现就不必管了(吐槽一下题目描述,没说四带二不算俩王,但测试点中确实不带)。还有一点值得注意的是大小顺序,首先是2不算顺子,其次1比3~13都大,因此可以把大小统一减2,1、2改为12、13便于使用。

  先预处理出各个数字(以下都为预处理后的数字)的个数,开始分层爆搜。先提前说明各个数组,la[]为各个数字还剩几个没打,num[i]为数量为i的同数字牌还有几个

  第一至三层为顺子,它们可以搜索到自己,因为一套牌可以出现多个顺子,至于顺子的长度,从大到小进行枚举,原理见上然后将搜索完的目标再次指向自己,在函数最后向下一层搜索。

  第四,五层为带,四层为四带二,要注意是四带二不是四带一,因为这个卡了55%,带对带单都可以,又因为可以同时出四带两个单和四带两个双,因此需要引入一个bool型变量确认该次搜索由哪里传下来,若为上层则四带双和四带单都单独搜索,四带双继续指向本层,bool改变,只搜四带单,三同理。

  第五层就是处理散牌了,不解释。

  最后膜拜?大犇,有一个剪枝,若到盖层走的步数以比当前最优解大,则直接返回,貌似省了不少时间。

  本来就是搜索题,只能说这些了,其实主要还是代码能力和脑洞

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
int t,n,ans=0x7fffffff;
int sum[14],la[14],num[5];
void dfs6(int js){
    if(js>=ans)return;
    int jj=0;
    for(int i=4;i>=1;i--)
        jj+=num[i];
    ans=min(ans,jj+js);
    return;
}
void dfs5(int js,bool pd){ //3 _
    if(js>=ans)return;
    int nn[5];
    memcpy(nn,num,sizeof(num));
    if(!pd)
    {
        for(int i=num[3];i>=1;i--)
        {
            if(num[2]>=i)
            {
                memcpy(num,nn,sizeof(num));
                num[3]-=i;
                num[2]-=i;
                dfs5(js+i,1);
                memcpy(num,nn,sizeof(num));//记得还原,否则判断num[]将会失误。下同。 
            }
        }
    }
    for(int i=num[3];i>=1;i--)
    {
        if(num[1]>=i)
        {
            memcpy(num,nn,sizeof(num));
            num[3]-=i;
            num[1]-=i;
            dfs6(js+i);
            memcpy(num,nn,sizeof(num));
        }
    }
    memcpy(num,nn,sizeof(nn));
    dfs6(js);
}
void dfs4(int js,bool pd){      //4 2    
    if(js>=ans)    return;
    int nn[5];
    if(!pd)
    {
        memset(num,0,sizeof(num));
        for(int i=1;i<=13;i++) num[la[i]]++;
        memcpy(nn,num,sizeof(num));
        for(int i=num[4];i>=1;i--)
        {
            if(num[2]>=i*2)
            {
                memcpy(num,nn,sizeof(nn));
                num[4]-=i;
                num[2]-=i*2;
                dfs4(js+i,1);
                memcpy(num,nn,sizeof(nn)); 
            }        
        }
    }
    if(pd) memcpy(nn,num,sizeof(num));
    for(int i=num[4];i>=1;i--)
    {
        if(num[1]>=i*2)
        {
            memcpy(num,nn,sizeof(nn));
            num[4]-=i;
            num[1]-=i*2;
            dfs5(js+i,0);
            memcpy(num,nn,sizeof(nn));
        }
    }
    memcpy(num,nn,sizeof(nn));
    dfs5(js,0);
}
void dfs3(int js){    //1s
    if(js>=ans) return;
    int ll[14];
    memcpy(ll,la,sizeof(la));
    for(int l=12;l>=5;l--)
    {    
        for(int i=1;i<=12-l+1;i++)
        {
            bool yx=1;
            for(int j=i;j<=i+l-1;j++)
            {
                if(la[j]<1)
                {
                    yx=0;
                    break;
                }
            }
            if(yx)
            {
                memcpy(la,ll,sizeof(ll));
                for(int j=i;j<=i+l-1;j++)
                {
                    la[j]-=1;
                }
                dfs3(js+1);
                memcpy(la,ll,sizeof(ll));
            }
        }
    }
    memcpy(la,ll,sizeof(ll));
    dfs4(js,0);
}
void dfs2(int js){   //2s
    if(js>=ans)    return;
    int ll[14];
    memcpy(ll,la,sizeof(la));
    for(int l=11;l>=3;l--)
    {    
        for(int i=1;i<=12-l+1;i++)
        {
            bool yx=1;
            for(int j=i;j<=i+l-1;j++)
            {
                if(la[j]<2)
                {
                    yx=0;
                    break;
                }
            }
            if(yx)
            {
                memcpy(la,ll,sizeof(ll));
                for(int j=i;j<=i+l-1;j++)
                {
                    la[j]-=2;
                }
                dfs2(js+1);
                memcpy(la,ll,sizeof(ll));
            }
        }
    }
    memcpy(la,ll,sizeof(ll));
    dfs3(js);
}
void dfs1(int js){  //3s
    if(js>=ans) return;
    int ll[14];
    memcpy(ll,la,sizeof(la));
    for(int l=7;l>=2;l--)
    {    
        for(int i=1;i<=12-l+1;i++)
        {
            bool yx=1;
            for(int j=i;j<=i+l-1;j++)
            {
                if(la[j]<3)
                {
                    yx=0;
                    break;
                }
            }
            
            if(yx)
            {
                memcpy(la,ll,sizeof(ll));
                for(int j=i;j<=i+l-1;j++)
                {
                    la[j]-=3;
                }
                dfs1(js+1);
                memcpy(la,ll,sizeof(ll));
            }
        }
    }
    memcpy(la,ll,sizeof(ll));
    dfs2(js);
}
int main(){
    scanf("%d%d",&t,&n);
while(t--)
{
    memset(sum,0,sizeof(sum));
    memset(la,0,sizeof(la));
    memset(num,0,sizeof(num));
    ans=0x7fffffff;
    int a,b,c,d;
    for(int i=1;i<=n;i++)
    {
        int xx,yy;
        scanf("%d%d",&xx,&yy);
        if(xx==1)
            xx=12;
        else if(xx==2)
            xx=13;
        else xx-=2;
        if(xx==-2) xx=0;
        sum[xx]++;
    }
    memcpy(la,sum,sizeof(sum));
    dfs1(0);
    if(sum[0]) ans++;
    printf("%d\n",ans);
}
    //while(1);
    return 0;
}

 

7.30考试(第一发博文)