当前位置: 首页 > 工具软件 > Maniac > 使用案例 >

SGU132 Another Chocolate Maniac

云胤
2023-12-01

SGU132 Another Chocolate Maniac

题目大意

给出一个N*M的矩阵,其中某些格子为空
要求用最少的1*2的矩形,无覆盖的放入空格中,使得剩下的空格都不相邻
问最少需要多少个

算法思路

状态压缩DP,f[j][S][R]表示前j-2行符合要求,第j-1行无横向相邻空格
第j行的状态为S且最后两行纵向相邻空格的状态为R时的最小值
对于第一行,显然R必定为0,考察S的放置方式,作为边界条件
对于第j行,需要计算辅助状态g[S],表示后两行放置状态为S的最小值

  • 对于f[j-1][S][R],由于状态R中的列必须放置,对应更新g[S + R + R']的值
  • 然后枚举第j列中的放置位置,用1*2矩形的两种状态尝试覆盖,g[S] = min{g[S-Si] + 1}, Si in S

最后,超出g[S]中第j-1行合法的状态,算出对应的R,更新f[j][S][R]的值

时间复杂度: O(M×22N)

代码

/**
 * Copyright © 2015 Authors. All rights reserved.
 * 
 * FileName: 132.cpp
 * Author: Beiyu Li <sysulby@gmail.com>
 * Date: 2015-06-14
 */
#include <bits/stdc++.h>

using namespace std;

#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)

typedef long long LL;
typedef pair<int, int> Pii;

const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;

const int maxm = 70 + 5;

int m, n;
int s[maxm];
int f[2][1<<7][1<<7], g[1<<14];
int bits[1<<7];

bool check(int S)
{
        rep(i,n-1) if (((3 << i) & S) == (3 << i)) return false;
        return true;
}

int solve()
{
        int o = 0, half = (1 << n) - 1;
        memset(f[0], 0x3f, sizeof(f[0]));
        for (int S = s[0];; S = (S - 1) & s[0]) {
                f[o][S][0] = 0;
                rep(i,n) if ((1 << i) & S) {
                        if ((1 << ++i) & ~S) { f[o][S][0] = inf; break; }
                        ++f[o][S][0];
                }
                if (!S) break;
        }
        For(j,1,m-1) {
                o ^= 1;
                memset(g, 0x3f, sizeof(g));
                for (int S = s[j-1];; S = (S - 1) & s[j-1]) {
                        int R0 = (s[j-1] ^ S) & s[j];
                        for (int R = R0;; R = (R - 1) & R0) {
                                int S1 = S | R | R << n;
                                g[S1] = min(g[S1], f[o^1][S][R] + bits[R]);
                                if (!R) break;
                        }
                        if (!S) break;
                }
                int S0 = s[j] << n | s[j-1];
                rep(S,1<<(n*2)) if (S > half && (S & S0) == S) {
                        rep(i,n) if ((1 << (i + n)) & S) {
                                int S1 = 1 << (i + n);
                                if ((S1 >> n) & S)
                                        g[S] = min(g[S], g[S^S1^(S1>>n)] + 1);
                                if (i && ((S1 >> 1) & S))
                                        g[S] = min(g[S], g[S^S1^(S1>>1)] + 1);
                        }
                }
                memset(f[o], 0x3f, sizeof(f[o]));
                for (int S = S0;; S = (S - 1) & S0) {
                        int R = S0 ^ S;
                        if (g[S] != inf && check(R & half)) {
                                int &now = f[o][S>>n][(R&half)&(R>>n)];
                                now = min(now, g[S]);
                        }
                        if (!S) break;
                }
        }
        int ret = inf;
        for (int S = s[m-1];; S = (S - 1) & s[m-1]) {
                if (check(s[m-1] ^ S)) ret = min(ret, f[o][S][0]);
                if (!S) break;
        }
        return ret;
}

int main()
{
        rep(S,1<<7) bits[S] = (S? bits[S^(S&-S)] + 1: 0);
        scanf("%d%d", &m, &n);
        rep(j,m) {
                char buf[10];
                scanf("%s", buf);
                rep(i,n) s[j] = s[j] << 1 | (buf[i] == '.');
        }
        printf("%d\n", solve());

        return 0;
}

 类似资料:

相关阅读

相关文章

相关问答