测试地址:采油区域
题目大意:给定一个
做法:这道题目需要用到分类讨论+动态规划。
因为不能相交,所以三个正方形区域的位置关系一定可以被归为下列情况之一:
1.三个正方形被一条横向的分界线间隔,可能的情况有:
(1)上面有两个,下面有一个。
(2)上面有一个,下面有两个。
2.三个正方形被一条纵向的分界线间隔,可能的情况有:
(1)左边有两个,右边有一个。
(2)左边有一个,右边有两个。
而在同一个区域的两个正方形要么被一条横向的分界线间隔,要么被一条纵向的分界线间隔。因此,我们只需枚举分界线,按照这种方法分割区域后,每个区域再找出一个最大的正方形即可。
枚举分界线是
由于没有图,我也解释不太清楚了,详细看代码吧。优化后的算法复杂度为
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
int n,m,k;
ll map[1510][1510],sum[1510][1510]={0},bsum[1510][1510]={0};
ll mx1[1510][1510]={0},mx2[1510][1510]={0},mx3[1510][1510]={0},mx4[1510][1510]={0};
ll mx5[1510]={0},mx6[1510]={0};
ll ans=0;
int main()
{
scanf("%d%d%d",&m,&n,&k);
for(int i=1;i<=m;i++)
{
int tot=0;
for(int j=1;j<=n;j++)
{
scanf("%lld",&map[i][j]);
tot+=map[i][j];
sum[i][j]=sum[i-1][j]+tot;
}
}
for(int i=k;i<=m;i++)
for(int j=k;j<=n;j++)
bsum[i][j]=sum[i][j]-sum[i-k][j]-sum[i][j-k]+sum[i-k][j-k];
for(int i=k;i<=m;i++)
{
ll mx=0;
for(int j=k;j<=n;j++)
{
mx=max(mx,bsum[i][j]);
mx1[i][j]=max(mx1[i-1][j],mx);
}
}
for(int i=m;i>=k;i--)
{
ll mx=0;
for(int j=n;j>=k;j--)
{
mx=max(mx,bsum[i][j]);
mx2[i][j]=max(mx2[i+1][j],mx);
}
}
for(int i=k;i<=m;i++)
{
ll mx=0;
for(int j=n;j>=k;j--)
{
mx=max(mx,bsum[i][j]);
mx3[i][j]=max(mx3[i-1][j],mx);
}
}
for(int i=m;i>=k;i--)
{
ll mx=0;
for(int j=k;j<=n;j++)
{
mx=max(mx,bsum[i][j]);
mx4[i][j]=max(mx4[i+1][j],mx);
}
}
for(int i=k;i<=m;i++)
for(int j=k;j<=n;j++)
mx5[i]=max(mx5[i],bsum[i][j]);
for(int j=k;j<=n;j++)
for(int i=k;i<=m;i++)
mx6[j]=max(mx6[j],bsum[i][j]);
for(int i=k;i<=m-k;i++)
for(int j=k;j<=n-k;j++)
{
ans=max(ans,mx1[i][j]+mx2[i+k][k]+mx3[i][j+k]);
ans=max(ans,mx1[m][j]+mx2[i+k][j+k]+mx3[i][j+k]);
ans=max(ans,mx1[i][n]+mx2[i+k][j+k]+mx4[i+k][j]);
ans=max(ans,mx1[i][j]+mx2[k][j+k]+mx4[i+k][j]);
}
ll mmx1=0,mmx2;
for(int i=k;i<=m-2*k;i++)
{
mmx1=max(mmx1,mx5[i]);
mmx2=0;
for(int j=i+k;j<=m-k;j++)
{
mmx2=max(mmx2,mx5[j]);
ans=max(ans,mmx1+mmx2+mx2[j+k][k]);
}
}
mmx1=0;
for(int i=k;i<=n-2*k;i++)
{
mmx1=max(mmx1,mx6[i]);
mmx2=0;
for(int j=i+k;j<=n-k;j++)
{
mmx2=max(mmx2,mx6[j]);
ans=max(ans,mmx1+mmx2+mx2[k][j+k]);
}
}
printf("%lld",ans);
return 0;
}