CF1304F1 - Animal Observation(easy version)
题意
N
N
N天,
M
M
M块区域,
a
i
j
a_{ij}
aij为第
i
i
i天第
j
j
j块区域的权值,每一天可以覆盖当前天和下一天的长度为
K
K
K的区域,求最大权值和
N
≤
50
,
M
≤
20000
,
K
≤
m
i
n
(
M
,
20
)
N \leq 50,M\leq20000,K\leq min(M,20)
N≤50,M≤20000,K≤min(M,20)
题解
比较明显的
D
P
DP
DP
记
f
[
i
]
[
l
]
f[i][l]
f[i][l]为第
i
i
i天覆盖
[
l
,
r
]
[l,r]
[l,r]所能获得的最大权值,其中
r
=
l
+
K
−
1
r=l+K-1
r=l+K−1
因为第
i
i
i天能覆盖
i
+
1
i+1
i+1天,所以我们只需要考虑重复计算的部分即可
当前为第
i
i
i天,
i
−
1
i-1
i−1天覆盖
[
q
l
,
q
r
]
[ql,qr]
[ql,qr],则有以下几种情况:
①
q
r
<
l
−
K
+
1
qr<l-K+1
qr<l−K+1或
q
l
>
r
ql>r
ql>r
无重复计算部分
②
l
−
K
+
1
≤
q
l
≤
l
l-K+1\leq ql \leq l
l−K+1≤ql≤l
重复计算
[
l
,
q
r
]
[l, qr]
[l,qr]
③
l
<
q
l
≤
r
l<ql\leq r
l<ql≤r
重复计算
[
q
l
,
r
]
[ql, r]
[ql,r]
对于①,我们可以提前处理好
l
m
a
x
[
l
−
K
]
=
max
j
=
1
l
−
1
f
[
i
−
1
]
[
j
]
lmax[l-K]=\displaystyle\max_{j=1}^{l-1}f[i-1][j]
lmax[l−K]=j=1maxl−1f[i−1][j]
r
m
a
x
[
r
+
1
]
=
max
j
=
r
+
1
M
f
[
i
−
1
]
[
j
]
rmax[r+1]=\displaystyle\max_{j=r+1}^{M}f[i-1][j]
rmax[r+1]=j=r+1maxMf[i−1][j]
对于②③,简单版本 K K K比较小,我们可以 f o r for for循环找
代码
#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;
}