SGU 250 Constructive Plan(面积最大的三个矩形)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=250

题意:给出一个01矩阵。要求选出三个矩形A、B、C。ABC的面积均大于0且相邻,且B的宽度要小于AC的宽度(就是横向的长度)。

思路:g[i][k]表示从第i行到第k行向右延伸的最大长度,n1[i][k]表示从第i行向下到第k行的最大矩形的行编号(可能小于k),n2[i][k]表示从第k行向上到第i行为止最大面积的行编号。然后枚举中间矩形的x方向的位置。

#include <cstdio>

#include <algorithm>

using namespace std;



const int N=185;

int p[N][N],g[N][N],n1[N][N],n2[N][N];

int n,m;



int main()

{

    scanf("%d%d",&n,&m);

    int i,j,k;

    for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%d",&p[i][j]);

    int ans=0,x1,x2,x3,x4,y1,y2,y3,y4;

    for(j=m;j>=1;j--)

    {

        for(i=1;i<=n;i++)

        {

            for(k=i;k<=n&&!p[k][j];k++) g[i][k]++;

            for(;k<=n;k++) g[i][k]=0;

        }

        for(i=1;i<=n;i++)

        {

            n1[i][i]=i;

            for(k=i+1;k<=n;k++)

            {

                if(g[i][n1[i][k-1]]*(n1[i][k-1]-i+1)<g[i][k]*(k-i+1)) n1[i][k]=k;

                else n1[i][k]=n1[i][k-1];

            }

        }

        for(k=n;k>=1;k--)

        {

            n2[k][k]=k;

            for(i=k-1;i>=1;i--)

            {

                if(g[n2[i+1][k]][k]*(k-n2[i+1][k]+1)<g[i][k]*(k-i+1)) n2[i][k]=i;

                else n2[i][k]=n2[i+1][k];

            }

        }



        for(i=1;i<=n;i++) if(g[i][i]) for(k=i+2;k<=n&&g[k][k];k++)

        {

            int a,b,c,all,low,high,mid,U,D;

            b=g[i+1][k-1];

            if(b<=0) break;

            b=min(b,min(g[i][i],g[k][k]));

            low=1;high=i;

            while(low<=high)

            {

                mid=(low+high)>>1;

                if(g[n2[mid][i]][i]>=b) high=mid-1,a=mid;

                else low=mid+1;

            }

            if(g[n2[a][i]][i]<b) continue;

            low=k;high=n;

            while(low<=high)

            {

                mid=(low+high)>>1;

                if(g[k][n1[k][mid]]>=b) low=mid+1,c=mid;

                else high=mid-1;

            }

            if(g[k][n1[k][c]]<b) continue;



            U=n2[a][i],D=n1[k][c];

            a=g[U][i],c=g[k][D];

            all=a*(i-U+1)+b*(k-i-1)+c*(D-k+1);

            if(b==a||b==c)

            {

                if(b<=1||--all<=ans) continue;

                ans=all;

                y1=j,y2=j+a-1,y3=j+b-2,y4=j+c-1;

                x1=U,x4=D;

                if(b==a) x2=k-2,x3=k;

                else x2=i,x3=i+2;

            }

            else if(all>ans)

            {

                ans=all;

                y1=j,y2=j+a-1,y3=j+b-1,y4=j+c-1;

                x1=U,x2=i,x3=k,x4=D;



            }

        }

   }

   if(ans<5)  return puts("-1"),0;

   for(i=x1;i<=x2;i++) for(j=y1;j<=y2;j++) p[i][j]=8;

   for(i=x2+1;i<x3;i++) for(j=y1;j<=y3;j++) p[i][j]=8;

   for(i=x3;i<=x4;i++) for(j=y1;j<=y4;j++) p[i][j]=8;

   printf("%d\n",ans);

   for(i=1;i<=n;i++)

   {

       for(j=1;j<=m;j++) printf("%d ",p[i][j]);

       puts("");

   }

   return 0;

}

  

你可能感兴趣的:(struct)