[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); }