首页 > 代码库 > zoj 3669 Japanese Mahjong I

zoj 3669 Japanese Mahjong I

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3669

题目大意:就是给你一副牌,问你胡牌的方式有几种,并输出方式。。。。。

思路:因为一副牌的数量不多,所以可以直接枚举每一张牌,判断加上这张牌后能否胡牌。。。


code:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>

using namespace std;

struct node
{
    int num;
    char kind;
}s[1000];

char str[100];
int a[4][15];
int ta[4][15];
int len,cnt;

int find(int num)
{
    int i,j;
    if(num==0) return 1;
    for(i=0;i<4;i++)       //判断三个为一组的情况
    {
        for(j=1;j<=9;j++)
        {
            if(a[i][j]<3) continue;
            a[i][j]-=3;
            if(find(num-1)) return 1;
            a[i][j]+=3;     //注意这儿的回溯
        }
    }
    for(i=0;i<3;i++)      //判断连牌的情况,并且连牌只可能前三类牌中出现
    {
        for(j=1;j<=7;j++)
        {
            if(a[i][j]&&a[i][j+1]&&a[i][j+2])
            {
                a[i][j]--;
                a[i][j+1]--;
                a[i][j+2]--;
                if(find(num-1))
                {
                    return 1;
                }
                a[i][j]++;    //回溯
                a[i][j+1]++;
                a[i][j+2]++;
            }
        }
    }
    return 0;
}


int solve()
{
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=1;j<=9;j++)
        {
            if(a[i][j]<2) continue;
            if(i==3&&j<=7)
            {
                a[i][j]-=2;
                if(find(4)) return 1;
                a[i][j]+=2;
            }
            else if(i<3&&j<=9)
            {
                a[i][j]-=2;
                if(find(4)) return 1;
                a[i][j]+=2;
            }
        }
    }
    return 0;
}


int main()
{
    int i,j,k;
    while(scanf("%s",str)!=EOF)
    {
        cnt=0;
        memset(a,0,sizeof(a));
        for(i=0;i<26;i+=2)   //记录每类牌的数量
        {
            if(str[i+1]=='m')
            {
                a[0][str[i]-'0']++;
            }
            else if(str[i+1]=='p')
            {
                a[1][str[i]-'0']++;
            }
            else if(str[i+1]=='s')
            {
                a[2][str[i]-'0']++;
            }
            else if(str[i+1]=='z')
            {
                a[3][str[i]-'0']++;
            }
        }
        char kind[5]="mpsz";
        for(i=1;i<=27+7;i++)  //枚举每张牌表并判断
        {
            int id=(i-1)/9;
            int no=i%9;
            if(no==0)
            {
                no=9;
            }
            memcpy(ta,a,sizeof(a));
            if(id<4&&a[id][no]<4)
            {
                a[id][no]++;
            }
            else
            {
                continue;
            }
            if(solve())   //如果能胡牌,则记录下来
            {
                s[cnt].num=no;
                s[cnt++].kind=kind[id];
            }
            memcpy(a,ta,sizeof(ta));
        }
        if(cnt==0)
        {
            printf("0\n");
        }
        else
        {
            printf("%d ",cnt);
            for(i=0;i<cnt;i++)
            {
                printf("%d%c",s[i].num,s[i].kind);
            }
            printf("\n");
        }
    }
    return 0;
}



zoj 3669 Japanese Mahjong I