前置芝士:
简单的前缀和。
简要题意
有 $ n\times m$个数组成一个矩阵,第 i i i 行选择前 c i > 0 c_i>0 ci>0 个数 a i , 1 , a i , 2 , … , a i , c i a_{i,1} ,a_{i,2},…,a_{i,c_i} ai,1,ai,2,…,ai,ci,问满足 c 1 > c 2 < c 3 > c 4 … c_1 > c_2 < c_3 >c_4 … c1>c2<c3>c4…的前提下 ∑ i = 1 n ∑ j = 1 c i a i , j \sum_{i=1}^n \sum_{j = 1}^{c_i}a_{i, j} ∑i=1n∑j=1ciai,j的最大值是多少。
Solution
读入时,预处理前缀和—>
sum[i][j] = sum[i][j - 1] + a[i][j];
令 f i , j f_{i,j} fi,j 表示第 i i i 行第 j j j 列最大值, g i , j g_{i,j} gi,j 表示第 i i i 行前 j j j 个 f i , j f_{i,j} fi,j的最大值, t i , j t_{i,j} ti,j 表示其后 m − j + 1 m - j + 1 m−j+1 个的最大值。每次更新即可。最后输出最后一行中最大的值。(别忘了使 g i , 0 g_{i,0} gi,0 和 t i , m + 1 t_{i,m+1} ti,m+1 设为 -inf,是为了应付全为负的情况)—>
for(int i = 1; i <= n; i++){
g[i][0] = -inf;
t[i][m + 1] = -inf;
for(int j = 1; j <= m; j++){
if(i % 2){
f[i][j] = g[i - 1][j - 1] + sum[i][j];
}
else {
f[i][j] = t[i - 1][j + 1] + sum[i][j];
}
g[i][j] = max(g[i][j - 1], f[i][j]);
}
for(int j = m; j >= 1; j--){
t[i][j] = max(t[i][j + 1], f[i][j]);
}
}
献上完整代码—>
#include <cstdio>
#include <algorithm>
#define PT 520
#define inf 1023456789
#define ll long long
using namespace std;
ll n, m, a[1505][1505], sum[1505][1505];
ll f[1505][1505], g[1505][1505], t[1505][1505], maxn = -inf;
int main(){
scanf("%lld%lld",&n,&m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
scanf("%lld",&a[i][j]), sum[i][j] = sum[i][j - 1] + a[i][j];
for(int i = 1; i <= n; i++){
g[i][0] = -inf;
t[i][m + 1] = -inf;
for(int j = 1; j <= m; j++){
if(i % 2){
f[i][j] = g[i - 1][j - 1] + sum[i][j];
}
else {
f[i][j] = t[i - 1][j + 1] + sum[i][j];
}
g[i][j] = max(g[i][j - 1], f[i][j]);
}
for(int j = m; j >= 1; j--){
t[i][j] = max(t[i][j + 1], f[i][j]);
}
}
for(int j = 1; j <= m; j++)
maxn = max(maxn, f[n][j]);
printf("%lld\n",maxn);
}
完结撒花✿✿ヽ(°▽°)ノ✿