洛谷P1169 [ZJOI2007]棋盘制作 悬线法

题目链接

首先了解一下悬线法:《浅谈用极大化思想解决最大子矩阵问题》

对于这道题,障碍点就是与当前点颜色相同的点,其他就照着模板做就好。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
int n,m,bd[2010][2010],l[2010][2010],r[2010][2010],ht[2010][2010];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&bd[i][j]);
            l[i][j]=j;r[i][j]=j;ht[i][j]=1; //给悬线ij赋初值 
        }
    for(int i=1;i<=n;i++)
        for(int j=2;j<=m;j++)
            if(bd[i][j]!=bd[i][j-1])
                l[i][j]=l[i][j-1];  //悬线ij可以向左延伸 
    for(int i=1;i<=n;i++)
        for(int j=m-1;j>=1;j--)
            if(bd[i][j]!=bd[i][j+1])
                r[i][j]=r[i][j+1];  //悬线ij向右延伸 
    for(int i=2;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(bd[i][j]!=bd[i-1][j])
            {
                ht[i][j]=ht[i-1][j]+1;  //悬线ij向上延伸 
                l[i][j]=max(l[i][j],l[i-1][j]);  //悬线ij收缩左区间 
                r[i][j]=min(r[i][j],r[i-1][j]);  //收缩右区间 
            }
            
    int ans1=0,ans2=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            int a=r[i][j]-l[i][j]+1,b=ht[i][j];  //悬线ij对应矩形宽为悬线ij左右延伸的距离,高为ij向上延伸距离 
            ans1=max(ans1,min(a,b)*min(a,b));  //对应正方形面积 
            ans2=max(ans2,a*b);  //矩形面积 
        }
    printf("%d
%d
",ans1,ans2);
    return 0;
}

 

原文地址:https://www.cnblogs.com/BakaCirno/p/11531236.html