[JSOI2007]麻将
Description
Solution
看这个数据范围就能想出来是\(O(n^2m)\)的,枚举听牌我知道,枚举对子我也知道,但是,判的时候竟然是贪心??从\(1\)到\(n\),先做刻子,再做顺子。
Code
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <vector>
namespace wyx {
int read() {
int ans = 0, fl = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') fl = -1;
c = getchar();
}
ans = c - '0';
for (c = getchar(); c >= '0' && c <= '9'; c = getchar())
ans = ans * 10 + c - '0';
return ans * fl;
}
const int N = 410;
const int ha = 10000;
int n, m;
int cnt[N], tmp[N];
std::vector<int> ans;
bool check() {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) tmp[j] = cnt[j];
if (tmp[i] < 2) continue;
tmp[i] -= 2;
for (int j = 1; j <= n; ++j) {
tmp[j] %= 3;
if (tmp[j] &&
((j + 2 > n) || (tmp[j + 2] < tmp[j]) || tmp[j + 1] < tmp[j])) {
break;
}
tmp[j + 1] -= tmp[j];
tmp[j + 2] -= tmp[j];
if (j == n) return true;
}
}
return false;
}
void main() {
n = read(), m = read();
m = 3 * m + 1;
for (int i = 1; i <= m; ++i) {
cnt[read()]++;
}
for (int i = 1; i <= n; ++i) {
cnt[i]++;
if (check()) ans.push_back(i);
cnt[i]--;
}
if (ans.empty())
puts("NO");
else
for (int i = 0; i < (int)ans.size(); ++i) {
printf("%d ", ans[i]);
}
}
} // namespace wyx
int main() {
wyx::main();
return 0;
}