悬线法
Posted mmminoz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了悬线法相关的知识,希望对你有一定的参考价值。
悬线法
•用途
针对求给定矩阵中满足某条件的极大矩阵,比如“面积最大的长方形、正方形”“周长最长的矩形等等”。
•思路
悬线法是一条竖线,这条竖线要满足上端点在整个矩形上边界或者是一个障碍点。
然后以这条悬线进行左右移动,直到移至障碍点或者是矩阵边界,进而确定这条悬线所在的极大矩阵。
也就是说,我们要针对矩阵中每个点进行求极大矩阵的操作,
所以我们需要Left[]数组存每个点能到达的最右位置,Right[]数组存放每个点能到达的最左位置,Up[]数组位置。
设置好这些数组之后,我们开始遍历矩阵中的每个点map[i,j],把每个点和上一个点(mP[i-1][j])的Left和Right进行比较,
分别取最大和最小,Up则是上一个点的Up+1,进而求出面积进行比较。(参考此处)
维护三个二维数组,Left,Right,Up数组。
Left数组存储从map[i][j]这个点出发,满足条件能到达的最右边地方。
Right数组存储从map[i][j]这个点出发,满足条件能到达的最左边地方。
Up数组,直接存储从这点以上满足条件的能到达的最大长度。
•例题
① 洛谷P1169 传送门
悬线法裸题
需要注意的是最大正方形肯定是在最大长方形内部,以长方形的较短的边为边
View Code1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=2005; 4 int a[maxn][maxn]; 5 int l[maxn][maxn],r[maxn][maxn],up[maxn][maxn]; 6 int n,m; 7 int s1,s2; 8 void Slove() 9 10 for(int i=1;i<=n;i++) 11 for(int j=2;j<=m;j++)//左边界 从左往右推 12 if(a[i][j]==(!a[i][j-1])) 13 l[i][j]=l[i][j-1]; 14 15 for(int i=1;i<=n;i++) 16 for(int j=m-1;j>=1;j--)//右边界 从右往左推 17 if(a[i][j]==(!a[i][j+1])) 18 r[i][j]=r[i][j+1]; 19 20 for(int i=1;i<=n;i++) 21 22 for(int j=1;j<=m;j++) 23 24 if(i>1&&a[i][j]==(!a[i-1][j])) 25 26 up[i][j]=up[i-1][j]+1; 27 l[i][j]=max(l[i][j],l[i-1][j]); 28 r[i][j]=min(r[i][j],r[i-1][j]); 29 30 int len1=r[i][j]-l[i][j]+1; 31 int len2=up[i][j]; 32 int curS=len1*len2; 33 s1=max(s1,curS); 34 //最大正方形肯定在长方形内部,以长方形短边为边长 35 s2=max(s2,min(len1,len2)*min(len1,len2)); 36 37 38 39 40 int main() 41 42 cin>>n>>m; 43 for(int i=1;i<=n;i++) 44 45 for(int j=1;j<=m;j++) 46 47 cin>>a[i][j]; 48 l[i][j]=j; 49 r[i][j]=j; 50 up[i][j]=1; 51 52 53 Slove(); 54 cout<<s2<<endl<<s1<<endl; 55
② Second Large Rectangle
以上是关于悬线法的主要内容,如果未能解决你的问题,请参考以下文章