【洛谷】棋盘制作-悬线法DP

传送门:洛谷-棋盘制作


题意

    小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一。小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。
    不过小Q还没有决定是找一个正方形的棋盘还是一个矩形的棋盘(当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色),所以他希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。


数据范围

对于100%的数据,N, M ≤ 2000


题解

    本蒟蒻看到这道题,就去学了一发悬线法(欸好像例题就是这道题)
悬线指的就是图中每条上端点是障碍物/矩形上边界的竖线。
    可以肯定有一个最大正方形是包含在最大矩形里的,变成为矩形较短的一边。然后我们用悬线法找出最大矩形就好了。


代码

#include
using namespace std;
int n,m,a,b;
int f[2005][2005];
int L[2005],R[2005],H[2005];
inline void fin(int x)
{
    for(int i=1;i<=m;i++){
        L[i]=1;R[i]=m;H[i]=0;
    }
    for(int i=1;i<=n;i++){
        int l=0,r=m+1;
        for(int j=1;j<=m;j++){
           if(f[i][j]!=x){
           	 L[j]=1;
           	 l=j;
           	 H[j]=0;
           }else{
           	 H[j]++;
           	 L[j]=max(l+1,L[j]);
           }
        }
        for(int j=m;j>=1;j--){
            if(f[i][j]!=x){
                R[j]=m;
                r=j;
            }else{
                R[j]=min(r-1,R[j]);
            }
            int now=min(H[j],(R[j]-L[j]+1));
            a=max(a,now*now);
            b=max(b,H[j]*(R[j]-L[j]+1));
        }
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++){
     	scanf("%d",&f[i][j]);
     	if((i+j)%2) f[i][j]=!f[i][j];
     }
    fin(0);fin(1);
    printf("%d\n%d\n",a,b);
    return 0;
}

你可能感兴趣的:(悬线法)