AmazingCounters.com

[BZOJ]1177: [Apio2009]Oil

题目大意:给出一个n*m的矩阵,选出3个不相交的k*k子矩阵,使得子矩阵中元素和最大。(k<=n,m<=1500)

思路:选出的子矩阵有3种情况:横着排三个、竖着排三个、三角状分布(其中有四种朝向),分情况判一判就好了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char B[1<<24],*S=B,C;int X;
inline int read()
{
    while((C=*S++)<'0'||C>'9');
    for(X=C-'0';(C=*S++)>='0'&&C<='9';)X=(X<<3)+(X<<1)+C-'0';
    return X;
}
#define MN 1500
#define L(i,k,n) for(register int i=k;i<=n;++i)
#define R(i,k,n) for(register int i=n-k;i;--i)
int s[MN+5][MN+5],f1[MN+5][MN+5],f2[MN+5][MN+5],f3[MN+5][MN+5],f4[MN+5][MN+5];
int main()
{
    fread(B,1,1<<24,stdin);
    int n,m,k,x,ans=0;
    n=read();m=read();k=read();
    L(i,1,n)L(j,1,m)s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+read();
    L(i,k,n)L(j,k,m)f1[i][j]=max(max(f1[i-1][j],f1[i][j-1]),s[i][j]-s[i-k][j]-s[i][j-k]+s[i-k][j-k]);
    L(i,k,n)R(j,k,m)f2[i][j]=max(max(f2[i-1][j],f2[i][j+1]),s[i][j+k]-s[i-k][j+k]-s[i][j]+s[i-k][j]);
    R(i,k,n)L(j,k,m)f3[i][j]=max(max(f3[i+1][j],f3[i][j-1]),s[i+k][j]-s[i][j]-s[i+k][j-k]+s[i][j-k]);
    R(i,k,n)R(j,k,m)f4[i][j]=max(max(f4[i+1][j],f4[i][j+1]),s[i+k][j+k]-s[i][j+k]-s[i+k][j]+s[i][j]);
    L(i,k<<1,n)L(j,k,m)ans=max(ans,f1[i-k][m]+s[i][j]-s[i-k][j]-s[i][j-k]+s[i-k][j-k]+f3[i][m]);
    L(j,k<<1,m)L(i,k,n)ans=max(ans,f1[n][j-k]+s[i][j]-s[i-k][j]-s[i][j-k]+s[i-k][j-k]+f2[n][j]);
    L(i,k,n-k)L(j,k,m-k)ans=max(ans,max(max(f1[i][j]+f2[i][j]+f3[i][m],f1[i][j]+f3[i][j]+f2[n][j]),
                                        max(f2[i][j]+f4[i][j]+f1[n][j],f3[i][j]+f4[i][j]+f1[i][m])));
    printf("%d",ans);
}

 

posted on 2017-03-31 09:15  ditoly  阅读(167)  评论(0编辑  收藏  举报