现在的位置: 首页 > 综合 > 正文

hdu 4431 Mahjong (模拟,枚举+dfs)

2013年11月01日 ⁄ 综合 ⁄ 共 2012字 ⁄ 字号 评论关闭

2012ACM天津赛区的一道题目。

很复杂的模拟,没有完全想清楚前别着急敲。我重写了2次代码才过。。。

题意不难理解,思路也很容易得到,枚举所有的牌,看加上这一张牌后能不能胡。

胡牌有3种规则:

1、 7对, 这种情况的判断只需要判断所有的牌是不是0或者2,出现其他情况直接false

2、十三幺,只要判断这十三张牌都出现过,并且没有出现过其他牌。

3、平胡,1个对子+4个组合(三张相同的,或者连续递增的。注意c类牌只能存在三张相同的组合)

首先任意选出一个对子,dfs看剩下的牌能不能凑成4个组合。

600+ms

#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node
{
    int x,y;
}ans[100];
int sum[4][15];
bool f1()
{
    for(int i=0;i<4;i++)
        for(int j=1;j<=9;j++)
            if(sum[i][j]&&sum[i][j]!=2) return false;
    return true;
}
bool f2()
{
    for(int i=0;i<3;i++)
        for(int j=1;j<=9;j+=8)
            if(!sum[i][j]) return false;
    for(int i=0;i<3;i++)
        for(int j=2;j<=8;j++)
            if(sum[i][j]) return false;
    for(int i=1;i<=7;i++)
        if(!sum[3][i]) return false;
    return true;
}
inline void fun(int j,int i,int num)
{
    for(int k=i;k<=i+2;k++) sum[j][k]+=num;
}
bool dfs(int s)
{
    if(s==4) return true;
    for(int j=0;j<3;j++)
    for(int i=1;i<=9;i++)
    {
        if(!sum[j][i]) continue;
        if(sum[j][i]&&!sum[j][i-1]&&!sum[j][i+1]&&sum[j][i]<=2) return false;
        if(sum[j][i]>=3)
        {
            sum[j][i]-=3;
            if(dfs(s+1)) {sum[j][i]+=3;return true;}
            sum[j][i]+=3;
        }
        if(sum[j][i]&&sum[j][i+1]&&sum[j][i+2])
        {
            fun(j,i,-1);
            if(dfs(s+1)) {fun(j,i,1);return true;}
            fun(j,i,1);
        }
    }
    return false;
}
bool istrue()
{
    int tot=0;
    for(int i=1;i<=7;i++)
    {
        if(!sum[3][i]) continue;
        if(sum[3][i]==3)
        tot++;
        else return false;
    }
    return dfs(tot);
}
bool f()
{
    for(int j=0;j<4;j++)
        for(int i=1;i<=9;i++)
        {
            if(sum[j][i]>=2)
            {
                sum[j][i]-=2;
                if(istrue()) {sum[j][i]+=2;return true;}
                sum[j][i]+=2;
            }
        }
    return false;
}
int main()
{
    char mp['z'];mp['m']=0;mp['s']=1;mp['p']=2;mp['c']=3;
    char mpp[]="mspc";
    int t,a,j,tot;
    char b;
    scanf("%d",&t);getchar();
    while(t--)
    {
        tot=0;
        memset(sum,0,sizeof(sum));
        for(int i=1;i<=13;i++)
        {
            scanf("%d%c",&a,&b);getchar();
            sum[mp[b]][a]++;
            tt[mp[b]]++;
        }
        for(j=0;j<4;j++)
        for(int i=1;i<=9;i++)
        {
            if(j==3&&i>7) break;
            if(sum[j][i]==4) continue;
            sum[j][i]++;
            if(f2())
            {
                ans[tot].x=i;
                ans[tot++].y=j;
            }
            else if((sum[j][i]==1||sum[j][i]==4)&&sum[j][i-1]==0&&sum[j][i+1]==0) {sum[j][i]--;continue;}
            else if(f1()||f())
            {
                ans[tot].x=i;
                ans[tot++].y=j;
            }
            sum[j][i]--;
        }
        if(!tot) {printf("Nooten\n");continue;}
        printf("%d",tot);
        for(int i=0;i<tot;i++)
            printf(" %d%c",ans[i].x,mpp[ans[i].y]);
        puts("");
    }
    return 0;
}

抱歉!评论已关闭.