[SCOI2009]粉刷匠
Description
Solution
考虑最基础的DP,枚举每个位置和从这个位置向前涂多远,\(O(n^5)\)DP,吸氧过了……
标解是\(O(n^4)\)
Code
#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <vector>
namespace wyx {
typedef long long ll;
typedef double ld;
ll read() {
char c;
ll ans = 0, fl = 1;
for (c = getchar(); c > '9' || c < '0'; c = getchar())
if (c == '-') fl = -1;
ans = c - '0';
for (c = getchar(); c >= '0' && c <= '9'; c = getchar())
ans = ans * 10 + c - '0';
// scanf("%lld\n", &ans);
return fl * ans;
}
const int N = 51;
const int M = 2501;
int f[N][N][M], n, m, T, s[N][N], p[N][N][N];
char a[N][N];
inline int max(const int &x, const int &y) { return x > y ? x : y; }
// f[i][j][t] = f[i][j-k][t-1] + w[j - k, j];
inline int w(const int &i, const int &j, const int &k) {
return ~p[i][j][k] ? p[i][j][k]
: p[i][j][k] = max(s[i][j] - s[i][k - 1],
j - k + 1 - s[i][j] + s[i][k - 1]);
}
void main() {
n = read();
m = read();
T = read();
int ans = 0;
memset(p, -1, sizeof p);
for (int i = 1; i <= n; ++i) {
scanf("%s", a[i] + 1);
for (int j = 1; j <= m; ++j) {
s[i][j] = s[i][j - 1] + a[i][j] - '0';
for (int t = 0; t <= T; ++t) f[i][j][t] = f[i - 1][m][t];
}
for (int t = 0; t <= T; ++t) f[i][0][t] = f[i - 1][m][t];
for (int j = 1; j <= m; ++j) {
for (int t = 1; t <= T; ++t) {
for (int k = j; k > 0; --k) {
f[i][j][t] =
max(f[i][j][t], f[i][k - 1][t - 1] + w(i, j, k));
// ans = max(ans, f[i][j][t]);
}
}
}
for (int j = 1; j <= m; ++j) ans = max(ans, f[i][j][T]);
}
printf("%d\n", ans);
}
} // namespace wyx
int main() {
wyx::main();
return 0;
}