悬线法
一、最大子矩陣問題
在一個給定的矩形中有一些障礙點(diǎn),找出內(nèi)部不包含障礙點(diǎn)的、輪廓與整個矩形平行或重合的最大子矩形。
二、定義子矩形
有效子矩形:內(nèi)部不包含障礙點(diǎn)的、輪廓與整個矩形平行或重合的子矩形。
極大子矩形:每條邊都不能向外擴(kuò)展的有效子矩形。
最大子矩形:所有有效子矩形中最大的一個(或多個)。
三、極大化思想
在一個有障礙點(diǎn)的矩形中最大子矩形一定是極大子矩形。
設(shè)計(jì)算法的思路:枚舉所有的極大子矩形,找到最大子矩形。
設(shè)NM分別為整個矩形的長和寬,S為內(nèi)部的障礙點(diǎn)數(shù)。
?
四、基本思想
【算法1】
時間復(fù)雜度:O(S^2) 空間復(fù)雜度:O(S)
由于極大子矩形的每一條邊都不能向外擴(kuò)展,那么極大子矩陣的每條邊要么覆蓋了障礙點(diǎn),要么與整個矩形的邊界重合
基本算法:枚舉上下左右四個邊界,然后判斷組成的矩形是否是有效子矩形。
復(fù)雜度:O(S^5) ?可以改進(jìn)的地方:產(chǎn)生了大量的無效子矩形。
初步改進(jìn)的算法:枚舉左右邊界,然后對處在邊界內(nèi)的點(diǎn)排序,每兩個相鄰的點(diǎn)和左右邊界組成一個矩形。
復(fù)雜度:O(S^3) 可以改進(jìn)的地方:枚舉了部分不是極大子矩形的情況。
綜上,設(shè)計(jì)算法的方向:
1、保證每一個枚舉的矩形都是有效的。
2、保證每一個枚舉的矩形都是極大的。
算法的過程:
枚舉極大子矩形的左邊界——>根據(jù)確定的左邊界,找出相關(guān)的極大子矩形——>檢查和處理遺漏的情況
(1)按照橫坐標(biāo)從小到大的順序?qū)⑺械狞c(diǎn)編號為1,2,3...
(2)首先選取1號點(diǎn)作為要枚舉的極大子矩形的左邊界,設(shè)定上下邊界為矩形的上下邊界
(3)從左到右掃描,第一次到2號點(diǎn),確定一個極大子矩形,修改上下邊界;第二次找到3號點(diǎn),以此類推。
(4)將左邊界移動到2號點(diǎn),3號點(diǎn),,,以同樣的方法枚舉
遺漏的情況:
1、矩形的左邊界與整個矩形的左邊界重合。解決方法:用類似的方法從左到右掃一遍
2、矩形的左邊界與整個矩形的左邊界重合,且矩形的右邊界與整個矩形的右邊界重合。解決方法:預(yù)處理時增加特殊判斷。
優(yōu)點(diǎn):利用的極大化思想,復(fù)雜度可以接受,編程實(shí)現(xiàn)簡單。
缺點(diǎn):使用有一定的局限性,不適合障礙點(diǎn)較密集的情況。
?
?
?
?
?
?
s為障礙點(diǎn)總數(shù)。
枚舉一個障礙點(diǎn)作為左邊界O(s),然后不斷向后掃得到極大子矩形O(s),總復(fù)雜度為O(s^2)。
當(dāng)1障礙點(diǎn)數(shù)較小時,可以使用算法1。
?
【算法2】
時間復(fù)雜度O(NM) 空間復(fù)雜度O(NM)
定義
有效豎線:除了兩個端點(diǎn)外,不覆蓋任何一個障礙點(diǎn)的豎直線段。
懸線:上端覆蓋了一個障礙點(diǎn)或者到達(dá)整個矩形上邊界的有效線段。
每個懸線都與它底部的點(diǎn)一一對應(yīng),矩形中的每一個點(diǎn)(矩形頂部的點(diǎn)除外)都對應(yīng)了一個懸線。
懸線的個數(shù)=(N-1)*M;
如果把一個極大子矩形按照橫坐標(biāo)的不同切割成多個與y軸平行的線段,那么其中至少有一個懸線。
如果把一個懸線向左右兩個方向盡可能的移動,那么就得到了一個矩形,我們稱它為懸線對應(yīng)的矩形。
懸線對應(yīng)的矩形不一定是極大子矩形,因?yàn)橄逻吔缈赡苓€可以向下擴(kuò)展。
設(shè)計(jì)算法:
原理:所有懸線對應(yīng)矩形的集合一定包含了極大子矩形的集合。通過枚舉所有的懸線,找出所有的極大子矩形。
算法規(guī)模:
懸線個數(shù)=(N-1)×M
極大子矩形個數(shù)≤懸線個數(shù)
具體方法:
設(shè) H[i,j]為點(diǎn)(i,j)對應(yīng)的懸線的長度。
?L[i,j]為點(diǎn)(i,j)對應(yīng)的懸線向左最多能夠移動到的位置。
R[i,j]為點(diǎn)(i,j)對應(yīng)的懸線向右最多能夠移動到的位置。
!考慮點(diǎn)(i,j)對應(yīng)的懸線與點(diǎn)(i-1,j)對應(yīng)的懸線的關(guān)系(遞推思想):
如果(i-1,j)為障礙點(diǎn),那么,如圖所示,(i,j)對應(yīng)的懸線長度1,左右能移動到的位置是整個矩形的左右邊界。
即 H[i,j]=1,
???L[i,j]=0,R[i,j]=m
如果(i-1,j)不是障礙點(diǎn),那么,如圖所示,(i,j)對應(yīng)的懸線長度為(i-1,j)對應(yīng)的懸線長度+1。
即 H[i,j]=H[i-1,j]+1
?如果(i-1,j)不是障礙點(diǎn),那么,如圖所示,(i,j)對應(yīng)的懸線左右能移動的位置要在(i-1,j)的基礎(chǔ)上變化。
????????????????????L[i-1,j]
L[i,j]=max
????????????????????(i-1,j)左邊第一個障礙點(diǎn)的位置????????
?同理,也可以得到R[i,j]的遞推式
????????????????????????R[i-1,j]
?????R[i,j]=min????
????????????????????????(i-1,j)右邊第一個障礙點(diǎn)的位置????????????????????????????
優(yōu)點(diǎn): 復(fù)雜度與障礙點(diǎn)個數(shù)沒有直接關(guān)系。
缺點(diǎn):障礙點(diǎn)少時處理較復(fù)雜,不如算法1。
?
?
?
當(dāng)障礙點(diǎn)較多,n*m較小時,可以用懸線法。
時間復(fù)雜度為O(n*m)。
五、例題
https://www.luogu.org/problemnew/show/P1169(題解:https://blog.csdn.net/weixin_43272781/article/details/88061944)
?
?
參考文章
https://blog.csdn.net/Clove_unique/article/details/50512624
總結(jié)
- 上一篇: [ZJOI2007]棋盘制作
- 下一篇: 666RPG