CF1304F1 - Animal Observation(easy version)
题意
天,
块区域,
为第
天第
块区域的权值,每一天可以覆盖当前天和下一天的长度为
的区域,求最大权值和
题解
比较明显的
记
为第
天覆盖
所能获得的最大权值,其中
因为第
天能覆盖
天,所以我们只需要考虑重复计算的部分即可
当前为第
天,
天覆盖
,则有以下几种情况:
①
或
无重复计算部分
②
重复计算
③
重复计算
对于①,我们可以提前处理好
对于②③,简单版本 比较小,我们可以 循环找
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 2e4 + 10;
const int MAX_N = 55;
int N, M, K;
ll pre[MAX_N][MAX], f[MAX_N][MAX], lmax[MAX], rmax[MAX];
int main() {
scanf("%d%d%d", &N, &M, &K);
for (int i = 1; i <= N; i++)
for (int j = 1; j <= M; j++)
scanf("%d", &pre[i][j]), pre[i][j] += pre[i][j - 1];
ll ans = 0;
for (int i = 1; i <= N; i++) {
//预处理lmax和rmax
for (int j = 1; j <= M; j++) lmax[j] = rmax[j] = f[i - 1][j];
for (int j = 1 + 1; j <= M; j++) lmax[j] = max(lmax[j], lmax[j - 1]);
for (int j = M - 1; j >= 1; j--) rmax[j] = max(rmax[j], rmax[j + 1]);
for (int l = 1; l + K - 1 <= M; l++) {
int r = l + K - 1;
//第一类
if (l - K >= 1) f[i][l] = max(f[i][l], lmax[l - K]);
if (r + 1 <= M) f[i][l] = max(f[i][l], rmax[r + 1]);
//二三类
for (int ql = max(1, l - K + 1); ql <= r; ql++) {
int qr = ql + K - 1;
//减去重复部分
if (ql <= l) f[i][l] = max(f[i][l], f[i - 1][ql] - (pre[i][qr] - pre[i][l - 1]));
else f[i][l] = max(f[i][l], f[i - 1][ql] - (pre[i][r] - pre[i][ql - 1]));
}
//加上两行的
f[i][l] += pre[i][r] - pre[i][l - 1] + pre[i + 1][r] - pre[i + 1][l - 1];
ans = max(ans, f[i][l]);
}
}
printf("%lld\n", ans);
return 0;
}