刷题垂线法

Posted xwww666666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了刷题垂线法相关的知识,希望对你有一定的参考价值。

(luogu)

悬线的定义是这样的:

从每一个点向上走,知道遇到障碍点或顶边界。

那么我们可以轻松地得到悬线的一些性质:

  1. 每一个点对应一根悬线
  2. 每一根悬线都对应了一个高度等于悬线高度,宽度大于0的矩形

所以悬线法的步骤就是:找出每一个点对应的悬线的高度,然后向左右分别找出该悬线能拓展出的矩形的宽度。

 

题面:

小Q找到了一张由N×M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一。

小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。

当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色,

所以他希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。

 

棋盘制作

技术图片
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,m;
const int N=2003;
int d[N][N];
int ll[N][N],rr[N][N],up[N][N];

int main()
{
    //输入 
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&d[i][j]),
            up[i][j]=1,ll[i][j]=rr[i][j]=j;
    //悬线法 
    
    for(int i=1;i<=n;i++)
        for(int j=2;j<=m;j++)
            if(d[i][j]^d[i][j-1]) 
                ll[i][j]=ll[i][j-1];
    for(int i=1;i<=n;i++)
        for(int j=m-1;j;j--)
            if(d[i][j]^d[i][j+1]) 
                rr[i][j]=rr[i][j+1];
    for(int j=1;j<=m;j++)
        for(int i=2;i<=n;i++)
            if(d[i][j]^d[i-1][j]) 
                up[i][j]=up[i-1][j]+1,
                ll[i][j]=max(ll[i][j],ll[i-1][j]),
                rr[i][j]=min(rr[i][j],rr[i-1][j]);
    //统计答案 
    int s1=0,s2=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            int len=rr[i][j]-ll[i][j]+1;
            s1=max(s1,min(len,up[i][j]));
            s2=max(s2,len*up[i][j]);
        }
    printf("%d
%d
",s1*s1,s2);
    return 0;
}
View Code

 

以上是关于刷题垂线法的主要内容,如果未能解决你的问题,请参考以下文章

java刷题--88合并两个有序数组

java刷题--206反转链表

点到平面的距离怎么求?

Leetcode刷题Python11. 盛最多水的容器

leetcode刷题之回溯法

Java工程师面试题,二级java刷题软件