卧薪尝胆,厚积薄发。
APIO2009 采油区域
Date: Wed Sep 26 16:24:46 CST 2018
In Category:
NoCategory
Description:
给一个
$n\times m$
的网格,每个位置有权值,从中选出
$3$
个不相交的大小为
$k\times k$
的正方形,最大化权值和。
$1\leqslant n,m\leqslant1500$
Solution:
把一个矩形分成三部分,最多只有以下六种可能。
于是求出以每个点为左上角
$/$
左下角
$/$
右上角
$/$
右下角的
$k\times k$
的矩形的最大值,这个可以用二维前缀最大值来
$O(n^2)$
求,还要预处理某条线右边
$/$
左边选一个
$k\times k$
的矩形的最大值,然后暴枚边界线即可。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,k;
#define MAXN 1510
int val[MAXN][MAXN];
int s[MAXN][MAXN];
int lu[MAXN][MAXN],ld[MAXN][MAXN],ru[MAXN][MAXN],rd[MAXN][MAXN];
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",&val[i][j]);
for(int i = 1;i <= n;++i)for(int j = 1;j <= m;++j)s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + val[i][j];
for(int i = n;i >= k;--i)for(int j = m;j >= k;--j)s[i][j] = s[i][j] - s[i - k][j] - s[i][j - k] + s[i - k][j - k];
for(int i = k;i <= n;++i)for(int j = k;j <= m;++j)lu[i][j] = max(s[i][j],max(lu[i - 1][j],lu[i][j - 1]));
for(int i = n;i >= k;--i)for(int j = k;j <= m;++j)ld[i][j] = max(s[i][j],max(ld[i + 1][j],ld[i][j - 1]));
for(int i = k;i <= n;++i)for(int j = m;j >= k;--j)ru[i][j] = max(s[i][j],max(ru[i - 1][j],ru[i][j + 1]));
for(int i = n;i >= k;--i)for(int j = m;j >= k;--j)rd[i][j] = max(s[i][j],max(rd[i + 1][j],rd[i][j + 1]));
int ans = 0;
for(int i = k;i <= n - k;++i)for(int j = k;j <= m - k;++j)ans = max(ans,lu[i][j] + ru[i][j + k] + ld[i + k][m]);
for(int i = k;i <= n - k;++i)for(int j = k + k;j <= m;++j)ans = max(ans,ru[i][j] + rd[i + k][j] + lu[n][j - k]);
for(int i = k + k;i <= n;++i)for(int j = k;j <= m - k;++j)ans = max(ans,ld[i][j] + rd[i][j + k] + lu[i - k][m]);
for(int i = k;i <= n - k;++i)for(int j = k;j <= m - k;++j)ans = max(ans,lu[i][j] + ld[i + k][j] + ru[n][j + k]);
for(int i = k + k;i <= n - k;++i)for(int j = k;j <= m;++j)ans = max(ans,s[i][j] + lu[i - k][m] + ld[i + k][m]);
for(int i = k;i <= n;++i)for(int j = k + k;j <= m - k;++j)ans = max(ans,s[i][j] + lu[n][j - k] + ru[n][j + k]);
cout << ans << endl;
return 0;
}
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡