[JSOI2007]麻将

Description

BZOJ1028
Luogu4050

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;
}
posted @ 2018-10-25 20:39  wyxwyx  阅读(122)  评论(0编辑  收藏  举报