题目传送门
思路
发现数据范围允许我们枚举每一张牌作为听牌,并且可以枚举每个有可能成为对子的牌,所以直接枚举即可。由于枚举的数量较多,循环嵌套可以使用函数封装的办法。这样可以使代码更加简洁清晰。但是我没用
代码
/*
这一题的难点我认为在多层循环中的信息传递,如题,我用了两个信号变量--flag和outter,如果能够把内两层循环封装进函数内,会清晰且方便许多。
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 500;
int vis[N],Count[N], ori[N];
int n,m,a,yon = 0;
int main(){
cin >> n >> m;
for (int i = 1; i <= 3*m+1; i++){
cin >> a;
Count[a]++;
ori[a]++;
}
for (int i = 1; i <= n; i++){
//枚举听牌
int outter = 0;
ori[i]++;
for (int j = 1; j <= n; j++){
if (outter == 1) break;
int flag = 0;
//枚举对子
if (ori[j] >= 2){
//有潜力成为对子
ori[j] -= 2; //先把对子取走
for (int k = 1; k <= n+2; k++) Count[k] = ori[k]; //到n+2的意义在于,如果n-1,n两个造成了后面小于零,那么也不可以成功凑成一队。
for (int k = 1; k <= n+2; k++){
if (Count[k] < 0) {
flag = 1;
break;
}
Count[k] %= 3; //取走刻字
Count[k+1] -= Count[k];
Count[k+2] -= Count[k]; //取走顺子
}
ori[j] += 2;
if (flag == 0){
outter = 1;
}
}
}
if (outter == 1){
yon = 1;
cout << i << " ";
}
ori[i]--;
}
if (yon == 0) cout << "NO";
return 0;
}