【BZOJ1028】[JSOI2007]麻将(贪心)

【BZOJ1028】[JSOI2007]麻将(贪心)

题面

BZOJ
洛谷

题解

感觉好久没打过麻将了,似乎都快不会打了。
这个数据范围看着就觉得是\(O(n^2m)\)
那么就枚举听哪张牌,然后枚举哪张是一对牌
考虑如何\(check\)剩下的牌是否能够构成顺子或者刻子(这叫法好别扭啊)。
那就从前往后搞,能够组成刻子就全组了,不行就组顺子(平时打麻将似乎也是这样的,虽然只有\(4\)张相同的)

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 404
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
int a[MAX],b[MAX],n,m,S[MAX],top;
bool check()
{
	for(int i=1;i<=n;++i)
	{
		b[i]%=3;
		if(b[i+1]<b[i]||b[i+2]<b[i])return false;
		b[i+1]-=b[i];b[i+2]-=b[i];b[i]=0;
	}
	for(int i=1;i<=n;++i)if(b[i])return false;
	return true;
}
int main()
{
	n=read();m=read();
	for(int i=1;i<=3*m+1;++i)a[read()]+=1;
	for(int i=1;i<=n;++i)
	{
		bool fl=false;
		for(int j=1;j<=n;++j)
		{
			for(int k=1;k<=n;++k)b[k]=a[k];
			b[i]+=1;if(b[j]<2)continue;b[j]-=2;
			if(check()){fl=true;break;}
		}
		if(fl)S[++top]=i;
	}
	if(!top)puts("NO");
	else for(int i=1;i<=top;++i)printf("%d ",S[i]);
	return 0;
}

posted @ 2018-09-29 11:21  小蒟蒻yyb  阅读(201)  评论(1编辑  收藏  举报