http://acm.xidian.edu.cn/land/problem/detail?problem_id=1105
前年校赛的一道题,去年校赛前自己模拟做了那套,这道题没有出。现在来补了。
题意:一种新的麻将,只有一种花色但有M张牌,给出N张牌,求所有的听牌(只考虑2+3X的胡牌规则)。
把前面那道题改改就OK了。
#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
int N,M;
int num[300],tile[300],t[300],n[300];
bool used[300];
bool Fu(int newt)
{
int ok = false;
num[newt]++;
for (int i = 1;i <= N;i++) t[i] = tile[i];
t[N+1] = newt;
t[0] = t[N+2] = -1;
sort(t+1,t+N+2);
for (int i = 1;i <= N+1;i++) if (t[i] != t[i-1])
{
for (int j = 1;j <= M;j++) n[j] = num[j];
memset(used,0,sizeof(used));
int tt = t[i];
if (n[tt] < 2) continue;
used[i] = used[i+1] = true;
n[tt] -= 2;
int j;
for (j = 1;j <= N+1;j++) if (!used[j])
{
int t1 = t[j];
if (n[t1] >= 3)
{
n[t1] -= 3;
used[j] = used[j+1] = used[j+2] = 1;
}
while (n[t1] && n[t1+1] && n[t1+2])
{
n[t1] --,n[t1+1]--,n[t1+2]--;
for (int k1 = j+1;k1 <= N+1;k1++) if (!used[k1] && t[k1] == t1+1)
{
used[k1] = 1;
break;
}
for (int k1 = j+1;k1 <= N+1;k1++) if (!used[k1] && t[k1] == t1+2)
{
used[k1] = 1;
break;
}
}
if (n[t1]) break;
}
if (j == N+2)
{
ok = true;
break;
}
}
num[newt]--;
return ok;
}
int main()
{
freopen("test.txt","r",stdin);
int T;
scanf("%d",&T);
while (T--)
{
memset(num,0,sizeof(num));
scanf("%d%d",&N,&M);
for (int i = 1; i <= N; i++)
{
scanf("%d",&tile[i]);
num[tile[i]]++;
}
int ans[300],suma = 0;
for (int i = 1;i <= M;i++) if (num[i] < 4)
{
if (Fu(i)) ans[++suma] = i;
}
cout<<suma;
for (int i = 1;i <= suma;i++) cout<<" "<<ans[i];
cout<<endl;
}
return 0;
}