[BZOJ1177][Apio2009]Oil(暴力模拟)

题目描述

传送门

题目大意:给出一个n*m的矩阵,选出3个不相交的k*k的矩阵,使权值和最大。

题解

mx(i,j,1/2/3/4)表示左上/右上/左下/右下端点在(i,j)范围内的最大的矩形
ver/hor(i,j)表示横/竖在[i,j]范围内的最大的矩形(只有(1,i)(i,n)是所有的)
然后暴力枚举横竖切的划分、拆分成3份的划分即可
时间 O(n2)

代码

#include
#include
#include
#include
#include
using namespace std;
#define N 1505

int n,m,k,ans;
int a[N][N],s[N][N],mx[N][N][5],ver[N][N],hor[N][N];

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",&a[i][j]);
    for (int i=1;i<=m;++i)
        for (int j=1;j<=n;++j) s[j][i]=s[j-1][i]+a[j][i];
    for (int i=1;i<=n-k+1;++i)
    {
        int now=0;
        for (int j=1;j<=k;++j) now+=s[i+k-1][j]-s[i-1][j];
        mx[i][1][1]=mx[i][k][2]=mx[i+k-1][1][3]=mx[i+k-1][k][4]=now;
        ver[1][k]=max(ver[1][k],now);hor[i][i+k-1]=max(hor[i][i+k-1],now);
        for (int j=2;j<=m-k+1;++j)
        {
            now-=s[i+k-1][j-1]-s[i-1][j-1];
            now+=s[i+k-1][j+k-1]-s[i-1][j+k-1];
            mx[i][j][1]=mx[i][j+k-1][2]=mx[i+k-1][j][3]=mx[i+k-1][j+k-1][4]=now;
            ver[j][j+k-1]=max(ver[j][j+k-1],now);hor[i][i+k-1]=max(hor[i][i+k-1],now);
        }
    }
    for (int i=1;i<=n;++i)
    {
        for (int j=m;j>=1;--j)
            mx[i][j][3]=max(mx[i][j][3],max(mx[i-1][j][3],mx[i][j+1][3]));
        for (int j=1;j<=m;++j)
            mx[i][j][4]=max(mx[i][j][4],max(mx[i-1][j][4],mx[i][j-1][4]));
    }
    for (int i=n;i>=1;--i)
    {
        for (int j=m;j>=1;--j)
            mx[i][j][1]=max(mx[i][j][1],max(mx[i+1][j][1],mx[i][j+1][1]));
        for (int j=1;j<=m;++j)
            mx[i][j][2]=max(mx[i][j][2],max(mx[i+1][j][2],mx[i][j-1][2]));
    }
    for (int i=1;i<=n;++i)
    {
        hor[1][i]=max(hor[1][i],hor[1][i-1]);
        for (int j=1;j<=i;++j) hor[1][i]=max(hor[1][i],hor[j][i]);
    }
    for (int i=n;i>=1;--i)
    {
        hor[i][n]=max(hor[i][n],hor[i+1][n]);
        for (int j=n;j>=i;--j) hor[i][n]=max(hor[i][n],hor[i][j]);
    }
    for (int i=1;i<=m;++i)
    {
        ver[1][i]=max(ver[1][i],ver[1][i-1]);
        for (int j=1;j<=i;++j) ver[1][i]=max(ver[1][i],ver[j][i]);
    }
    for (int i=m;i>=1;--i)
    {
        ver[i][m]=max(ver[i][m],ver[i+1][m]);
        for (int j=m;j>=i;--j) ver[i][m]=max(ver[i][m],ver[i][j]);
    }
    for (int i=1;i<=n-k+1;++i) ans=max(ans,hor[1][i-1]+hor[i][i+k-1]+hor[i+k][n]);
    for (int i=1;i<=m-k+1;++i) ans=max(ans,ver[1][i-1]+ver[i][i+k-1]+ver[i+k][m]);
    for (int i=1;i<=n;++i)
        for (int j=1;j<=m;++j)
        {
            ans=max(ans,mx[1][j][1]+mx[i-1][j-1][4]+mx[i][j-1][2]);
            ans=max(ans,mx[1][j][1]+mx[i][j-1][4]+mx[i+1][j-1][2]);
            ans=max(ans,mx[1][j-1][2]+mx[i-1][j][3]+mx[i][j][1]);
            ans=max(ans,mx[1][j-1][2]+mx[i][j][3]+mx[i+1][j][1]);

            ans=max(ans,mx[1][j+1][1]+mx[i-1][j][4]+mx[i][j][2]);
            ans=max(ans,mx[1][j+1][1]+mx[i][j][4]+mx[i+1][j][2]);
            ans=max(ans,mx[1][j][2]+mx[i-1][j+1][3]+mx[i][j+1][1]);
            ans=max(ans,mx[1][j][2]+mx[i][j+1][3]+mx[i+1][j+1][1]);

            ans=max(ans,mx[i][1][1]+mx[i-1][j-1][4]+mx[i-1][j][3]);
            ans=max(ans,mx[i][1][1]+mx[i-1][j-1][4]+mx[i-1][j+1][3]);
            ans=max(ans,mx[i-1][1][3]+mx[i][j-1][2]+mx[i][j][1]);
            ans=max(ans,mx[i-1][1][3]+mx[i][j][2]+mx[i][j+1][1]);

            ans=max(ans,mx[i+1][1][1]+mx[i][j-1][4]+mx[i][j][3]);
            ans=max(ans,mx[i+1][1][1]+mx[i][j][4]+mx[i][j+1][3]);
            ans=max(ans,mx[i][1][3]+mx[i+1][j-1][2]+mx[i+1][j][1]);
            ans=max(ans,mx[i][1][3]+mx[i+1][j][2]+mx[i+1][j+1][1]); 
        }
    printf("%d\n",ans);
}

你可能感兴趣的:(题解,模拟)