bzoj2669 [cqoi2012]極小圧力DP +フォームおよび除外

トピックポータル

https://lydsy.com/JudgeOnline/problem.php?id=2669

問題の解決策

見つけることができます\(4 \回7 \)行列の、最大の極小点がためにそこにある(2 \回4 = 8 \ \) Aを、私たちはすべてのローカル最小形状に押すことができます場所ではありません選択されました。

小型から各グリッドを埋めるために大規模に、そして極小値が満たされた場合に周り、そしてグリッドが埋めることができないも意味がありません。だから何の前処理の各状態は、格子の数を記入して自由である状況が変わらない場合は、その後、それはとても転送することができます。

ステータスが変化した場合、それは地元の最小、直接の現在の状態と相まって、長い解答を記入することです。


しかし、私は問題があるでしょう:ポジションを埋めるために自由は、余分極小値を表示されることがあり、地元の最小極小値があった場所と言われるべきである - それは、直接、直接および除外のように見えます法的地位の様々な検索、DPについてです。

このDPの複雑さは、明らかです\(O(NM \ CDOT 8 \ CDOT 2 ^ 8)\)が、私は、検索を忘れる可能性が低いです。要するに、あなたは簡単に倒れることができます。

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back

template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}

typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;

template<typename I> inline void read(I &x) {
    int f = 0, c;
    while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    x = c & 15;
    while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    f ? x = -x : 0;
}

const int N = 4 * 7 + 7;
const int M = (1 << 8) + 7;
const int dx[] = {0, 1, 1, 1, 0, -1, -1, -1}, dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
const int P = 12345678;

int n, m, pcnt, cnt, S, ans;
pii p[N];
int wy[M], dp[N][M];
char a[N][N], b[N][N], mk[5][8];

inline int smod(int x) { return x >= P ? x - P : x; }
inline void sadd(int &x, const int &y) { x += y; x >= P ? x -= P : x; }
inline int fpow(int x, int y) {
    int ans = 1;
    for (; y; y >>= 1, x = (ll)x * x % P) if (y & 1) ans = (ll)ans * x % P;
    return ans;
}

inline void ycl() {
    S = (1 << cnt) - 1;
    memset(wy, 0, sizeof(wy));
    for (int s = 0; s <= S; ++s) {
        int &ans = wy[s];
        memset(mk, 0, sizeof(mk));
        for (int i = 1; i <= cnt; ++i) if (!((s >> (i - 1)) & 1)) {
            int x = p[i].fi, y = p[i].se;
            mk[x][y] = 1;
            for (int i = 0; i < 9; ++i) {
                int px = x + dx[i], py = y + dy[i];
                if (px < 1 || px > n || py < 1 || py > m) continue;
                mk[px][py] = 1;
            }
        }
        for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) if (!mk[i][j]) ++ans;
    }
}

inline void DP() {
    memset(dp, 0, sizeof(dp));
    dp[0][0] = 1;
    for (int i = 0; i < n * m; ++i) {
        for (int s = 0; s <= S; ++s) {
            sadd(dp[i + 1][s], (ll)dp[i][s] * (wy[s] - i) % P);
            for (int j = 1; j <= cnt; ++j) if (!((s >> (j - 1)) & 1))
                sadd(dp[i + 1][s ^ (1 << (j - 1))], dp[i][s]);
        }
    }
}

inline void calc() {
    cnt = 0;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) if (b[i][j]) p[++cnt] = pii(i, j);
    ycl();
    DP();
    if ((cnt - pcnt) & 1) sadd(ans, P - dp[n * m][S]);
    else sadd(ans, dp[n * m][S]);
}

inline void dfs(int x, int y) {
    if (x == n + 1) return calc();
    if (y == m) dfs(x + 1, 1); else dfs(x, y + 1);
    int flag = 1;
    for (int i = 0; i < 9; ++i) {
        int px = x + dx[i], py = y + dy[i];
        if (px < 1 || px > n || py < 1 || py > m) continue;
        if (b[px][py]) { flag = 0; break; }
    }
    if (a[x][y] || !flag) return;
    b[x][y] = 1;
    if (y == m) dfs(x + 1, 1); else dfs(x, y + 1);
    b[x][y] = 0;
}

inline void work() {
    for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) if (a[i][j])
        for (int k = 1; k <= n; ++k) for (int l = 1; l <= n; ++l) if (a[k][l])
            if (abs(i - k) <= 1 && abs(j - l) <= 1 && (i != k || j != l)) return (void)puts("0");
    memcpy(b, a, sizeof(a));
    dfs(1, 1);
    printf("%d\n", ans);
}

inline void init() {
    read(n), read(m);
    for (int i = 1; i <= n; ++i) {
        scanf("%s", a[i] + 1);
        for (int j = 1; j <= m; ++j) a[i][j] = a[i][j] == 'X', pcnt += a[i][j];
    }
}

int main() {
#ifdef hzhkk
    freopen("hkk.in", "r", stdin);
#endif
    init();
    work();
    fclose(stdin), fclose(stdout);
    return 0;
}

おすすめ

転載: www.cnblogs.com/hankeke/p/bzoj2669.html