UVa 11210 - Chinese Mahjong(枚举+搜索)

题目链接

分析:
身为一个麻将老手,我都不一定能”听“全牌
一共只有34种牌,我们可以考虑枚举每一张牌,
这样问题就可以转化成判断14张牌是否可以“和”

为此,我们可以枚举将牌,之后每次选三张作为刻子或者顺子
如图:选将有5种方式
这里写图片描述

为了快速的选出将,顺,刻,我们可以用一个34维向量表示每一张牌有多少,
除了第一次枚举将牌,我们每次只用考虑最小的牌在哪一个顺子或刻子里就好了

tip

每种牌只有4张

//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

const  char *mahjong[]={"1T","2T","3T","4T","5T","6T","7T","8T","9T","1S",
                        "2S","3S","4S","5S","6S","7S","8S","9S","1W","2W",
                        "3W","4W","5W","6W","7W","8W","9W","DONG","NAN","XI",
                        "BEI","ZHONG","FA","BAI"};
int mj[15],c[40];

int cl(char *s)
{
    for (int i=0;i<34;i++)
        if (strcmp(mahjong[i],s)==0) return i;
    return -1;
}

int solve(int num)                                              //当前已经有的3元组 
{
    int i;
    for (i=0;i<34;i++)                                          //刻子 
        if (c[i]>=3)
        {
            if (num==4) return 1;
            c[i]-=3;
            if (solve(num+1)) return 1;
            c[i]+=3;
        }

    for (i=0;i<27;i++)                                          //顺子 
        if (i%9<=6&&c[i+1]>=1&&c[i+2]>=1&&c[i]>=1)              //没有以8,9开头的顺子
        {
            if (num==4) return 1;
            c[i]--; c[i+1]--; c[i+2]--;
            if (solve(num+1)) return 1;
            c[i]++; c[i+1]++; c[i+2]++;
        } 

    return 0;
}

int check()
{
    for (int i=0;i<34;i++)        //每种牌都可以作为将
    {
        if (c[i]<2) continue;
        c[i]-=2;
        if (solve(1)) return 1;
        c[i]+=2;
    } 
    return 0;
}

int main()
{
    int cas=0;
    char s[10];
    while (scanf("%s",&s)==1)
    {
        if (s[0]=='0') break;
        printf("Case %d:",++cas);

        mj[0]=cl(s);
        for (int i=1;i<13;i++)
        {
            scanf("%s",&s);
            mj[i]=cl(s);
        }

        bool ff=0;
        for (int i=0;i<34;i++)
        {
            memset(c,0,sizeof(c));
            for (int j=0;j<13;j++) c[mj[j]]++;

            if (c[i]==4) continue;
            c[i]++;
            if (check())
            {
                ff=1;
                printf(" %s",mahjong[i]);
            }
            c[i]--;
        }

        if (!ff) printf(" Not ready");
        printf("\n");
    }
    return 0;
}
posted @ 2017-10-15 08:40  wtt3117  阅读(115)  评论(0编辑  收藏