BZOJ1177 [Apio2009]Oil(洛谷P3625)

枚举

BZOJ题目传送门
洛谷题目传送门

一点都不会的暴枚题

把原地图用两条垂直于边界的直线分成三块,让三个正方形分别在这三块里取。那么可以分成六种情况:

对第一行的情况枚举其交点。对于第二行的情况枚举其中一条直线,另一条离枚举的这条距离为k。要预处理四个数组分别表示点 i , j 左上/右上/左下/右下内的最大K*K正方形权值。

具体实现见代码(BZOJ不能用读优我也不知道为什么):

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1505
#define F inline
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
int n,m,k,ans,a[N][N],b[N][N],c[N][N],d[N][N],w[N][N],s[N][N];
//F char readc(){
//  static char buf[100000],*l=buf,*r=buf;
//  if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
//  return l==r?EOF:*l++;
//}
//F int _read(){
//  int x=0; char ch=readc();
//  while (!isdigit(ch)) ch=readc();
//  while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
//  return x;
//}
F int _read(){ int x; scanf("%d",&x); return x; } 
F void Make(){
    for (int i=k;i<=n;i++)
        for (int j=k;j<=m;j++)
            s[i][j]=w[i][j]-w[i-k][j]-w[i][j-k]+w[i-k][j-k];
    for (int i=k;i<=n;i++)
        for (int j=k;j<=m;j++)
            a[i][j]=max(s[i][j],max(a[i-1][j],a[i][j-1]));
    for (int i=k;i<=n;i++)
        for (int j=m-k;j;j--)
            b[i][j]=max(s[i][j+k],max(b[i-1][j],b[i][j+1]));
    for (int i=n-k;i;i--)
        for (int j=k;j<=m;j++)
            c[i][j]=max(s[i+k][j],max(c[i+1][j],c[i][j-1]));
    for (int i=n-k;i;i--)
        for (int j=m-k;j;j--)
            d[i][j]=max(s[i+k][j+k],max(d[i+1][j],d[i][j+1]));
}
int main(){
    n=_read(),m=_read(),k=_read();
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            w[i][j]=w[i][j-1]+w[i-1][j]-w[i-1][j-1]+_read();
    Make();
    for (int i=k;i<=n-k;i++)
        for (int j=k;j<=m-k;j++){
            ans=max(ans,a[i][j]+b[i][j]+c[i][m]);
            ans=max(ans,c[i][j]+d[i][j]+a[i][m]);
            ans=max(ans,a[i][j]+c[i][j]+b[n][j]);
            ans=max(ans,b[i][j]+d[i][j]+a[n][j]);
    }
    for (int i=k;i<=n-k;i++)
        for (int j=k;j<=m;j++)
            ans=max(ans,b[i][1]+d[i+k][1]+s[i+k][j]);
    for (int j=k;j<=m-k;j++)
        for (int i=k;i<=n;i++)
            ans=max(ans,c[1][j]+d[1][j+k]+s[i][j+k]);
    return printf("%d\n",ans),0;
}

猜你喜欢

转载自blog.csdn.net/a1799342217/article/details/81275058