题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1028
【分析】
枚举加上的那张等待牌。
统计出每个序数相同的牌的数量,然后按序数从小到大分牌。对于序数相同的牌,先考虑刻子(3个相同),然后剩下的牌按顺子分掉,分不掉就说明当前牌不是听牌。
简略的证明:3个顺子即3个刻子,所以优先考虑刻子;如果前面的牌都分完了,当前要分的同序数的牌还剩1或2个,那么必须弄成顺子分掉,分不掉显然就不是听牌了。
【代码】
#include <cstdio>
using namespace std;
const int maxn=410;
int a[maxn];
int t[maxn];
int n,m,x;
bool Hula;
bool Check()
{
for (int k=1;k<=n;k++)
{
bool Pass=true;
for (int i=1;i<=n;i++) t[i]=a[i];
t[k]-=2;
for (int i=1;i<=n;i++)
{
t[i]%=3;
if (t[i+1]<t[i] || t[i+2]<t[i]) {Pass=false;break;}
t[i+1]-=t[i],t[i+2]-=t[i];
t[i]=0;
}
if (Pass) return true;
}
return false;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=0;i<3*m+1;i++) scanf("%d",&x),a[x]++;
Hula=false;
for (int i=1;i<=n;i++)
{
a[i]++;
if (Check())
{
if (Hula) printf(" ");
Hula=true;
printf("%d",i);
}
a[i]--;
}
if (!Hula) printf("NO");
return 0;
}