麻将

· · 题解

麻将([JSOI2007])

原题链接:luogu P4050

解题思路:

这可是民间国粹啊!虽然我不会打

这题如果会打麻将的同学就可以很快的理解题意,像我这种不会的,得搞很久才明白。

由于胡要必定有一个对子,所以,我们可以枚举每一种可能性,使其凑成对子以上个数。然后继续进行各种刻子和顺子的判断。

AC代码如下:

#include<bits/stdc++.h>
using namespace std;

int n,m,t[4001],a[4001];
bool bj;

bool check()
{
    for(int i=1;i<=n;i++)
    {
        if(t[i]>=2)//只有凑成对子以上个数时才能胡牌。
        {
            bool ok=1;//进行标记是否找到。
            t[i]-=2;//将其当做对子。
            for(int j=1;j<=n+2;j++)a[j]=t[j];//不能改变原来数组的值。
            for(int j=1;j<=n+2;j++)
            {
                if(a[j]<0)//如果小于0则代表不能胡牌,直接退出循环,进行下一个对子的判断。
                {
                    ok=0;
                    break;
                }
                a[j]%=3;//刻子
                a[j+1]-=a[j];//顺子
                a[j+2]-=a[j];//顺子
            }
            t[i]+=2;
            if(ok)return 1;
        }
    }
    return 0;
}

int main()
{
    cin>>n>>m;
    for(int i=1,x;i<=m*3+1;i++)cin>>x,t[x]++;//用桶来存储麻将个数。
    for(int i=1;i<=n;i++)
    {
        t[i]++;
        if(check())bj=1,cout<<i<<" "; //只要找到一个解就标记找到了,并输出解。
        t[i]--;
    }
    if(!bj)cout<<"NO";
    return 0;
}