Loading

洛谷 P4158 [SCOI2009]粉刷匠

先考虑一块木板的情况:

每个格子只能被粉刷一次,所以不用考虑覆盖的问题,大可从前往后顺序粉刷。

\(f_{i, j}\) 表示前 \(i\) 个格子涂 \(j\) 次最多能粉刷正确的格子数,则可以得到转移方程:

\[f_{i, j} = \max_{1 \le k < i}\{f_{k, j - 1} + \max\{\text{Red}(k + 1, i), \text{Blue}(k + 1, i)\}\} \]

其中 \(\text{Red}(x, y)\) 表示区间 \([x, y]\) 内应该涂成红色的格子数,\(\text{Blue}(x, y)\) 表示区间 \([x, y]\) 内应该涂成蓝色的格子数。

\(\text{Red}(x, y)\)\(\text{Blue}(x, y)\) 该如何维护?

用前缀和维护区间和即可。

推广到多块木板:

我们还是对每块木板求一遍 \(f_{i, j}\),即求出 \(f_{i, j, k}\) 表示第 \(i\) 块木板的前 \(j\) 个格子涂 \(k\) 次最多能正确粉刷的格子数。

类似地,令 \(F_{i, j}\) 表示前 \(i\) 块木板涂 \(j\) 次最多能粉刷正确的格子数,则又可以得到转移方程:

\[F_{i, j} = \max_{0 \le k < j}\{F_{i - 1, k} + f_{i, M, j - k}\} \]

最后的答案就是 \(F_{N, T}\)

可以通过改变枚举顺序优化空间复杂度(不优化也无所谓)。

$\text{Code}$
#include <bits/stdc++.h>

#define MAXN 60
#define MAXT 2600

using namespace std;

int n, m, t;
int sum0[MAXN], sum1[MAXN], f[MAXN][MAXT], F[MAXT];
char s[MAXN];

template<typename _T>
void read(_T &_x) {
    _x = 0;
    _T _f = 1;
    char _ch = getchar();
    while (_ch < '0' || '9' < _ch) {
        if (_ch == '-') _f = -1;
        _ch = getchar();
    }
    while ('0' <= _ch && _ch <= '9') {
        _x = (_x << 3) + (_x << 1) + (_ch & 15);
        _ch = getchar();
    }
    _x *= _f;
}

template<typename _T>
void write(_T _x) {
    if (_x < 0) {
        putchar('-');
        _x = -_x;
    }
    if (_x > 9) write(_x / 10);
    putchar('0' + _x % 10);
}

int main() {
    read(n), read(m), read(t);
    while (n--) {
        scanf("%s", s + 1);
        memset(f, 0, sizeof(f));
        for (int i = 1; i <= m; i++) {
            sum0[i] = sum0[i - 1] + (s[i] == '0');
            sum1[i] = sum1[i - 1] + (s[i] == '1');
            for (int j = 1; j <= t; j++) {
                for (int k = j - 1; k < i; k++) {
                    f[i][j] = max(f[i][j], f[k][j - 1] + max(sum0[i] - sum0[k], sum1[i] - sum1[k]));
                }
            }
        }
        for (int i = t; i; i--) {
            for (int j = 0; j < i; j++) {
                F[i] = max(F[i], F[j] + f[m][i - j]);
            }
        }
    }
    write(F[t]);
    return 0;
}
posted @ 2022-11-11 11:21  Chy12321  阅读(20)  评论(0编辑  收藏  举报