【轉】【最大子矩陣問題】【懸線法】 學習筆記


學習材料:王知昆《淺談用極大化思想解決最大子矩陣問題》

【最大子矩陣問題】

在一個給定的矩形中有一些障礙點,找出內部不包含障礙點的、輪廓與整個矩形平行或重合的最大子矩形。

【定義子矩形】

有效子矩形:內部不包含障礙點的、輪廓與整個矩形平行或重合的子矩形。

極大子矩形:每條邊都不能向外擴展的有效子矩形。

最大子矩形:所有有效子矩形中最大的一個(或多個)。

【極大化思想】

在一個有障礙點的矩形中最大子矩形一定是極大子矩形。

設計算法的思路:枚舉所有的極大子矩形,找到最大子矩形。

設NM分別為整個矩形的長和寬,S為內部的障礙點數。

【算法1】

時間復雜度:O(S^2) 空間復雜度:O(S)

由於極大子矩形的每一條邊都不能向外擴展,那么極大子矩陣的每條邊要么覆蓋了障礙點,要么與整個矩形的邊界重合

基本算法:枚舉上下左右四個邊界,然后判斷組成的矩形是否是有效子矩形。

復雜度:O(S^5)  可以改進的地方:產生了大量的無效子矩形。

初步改進的算法:枚舉左右邊界,然后對處在邊界內的點排序,每兩個相鄰的點和左右邊界組成一個矩形。

復雜度:O(S^3) 可以改進的地方:枚舉了部分不是極大子矩形的情況。

綜上,設計算法的方向:

1、保證每一個枚舉的矩形都是有效的。

2、保證每一個枚舉的矩形都是極大的。

算法的過程:

枚舉極大子矩形的左邊界——>根據確定的左邊界,找出相關的極大子矩形——>檢查和處理遺漏的情況

(1)按照橫坐標從小到大的順序將所有的點編號為1,2,3...

(2)首先選取1號點作為要枚舉的極大子矩形的左邊界,設定上下邊界為矩形的上下邊界

(3)從左到右掃描,第一次到2號點,確定一個極大子矩形,修改上下邊界;第二次找到3號點,以此類推。

(4)將左邊界移動到2號點,3號點,,,以同樣的方法枚舉

遺漏的情況:

1、矩形的左邊界與整個矩形的左邊界重合。解決方法:用類似的方法從左到右掃一遍

2、矩形的左邊界與整個矩形的左邊界重合,且矩形的右邊界與整個矩形的右邊界重合。解決方法:預處理時增加特殊判斷。

優點:利用的極大化思想,復雜度可以接受,編程實現簡單。

缺點:使用有一定的局限性,不適合障礙點較密集的情況。

【算法2】

時間復雜度O(NM) 空間復雜度O(NM)

定義

有效豎線:除了兩個端點外,不覆蓋任何一個障礙點的豎直線段。

懸線:上端覆蓋了一個障礙點或者到達整個矩形上邊界的有效線段。

每個懸線都與它底部的點一一對應,矩形中的每一個點(矩形頂部的點除外)都對應了一個懸線。

懸線的個數=(N-1)*M;

如果把一個極大子矩形按照橫坐標的不同切割成多個與y軸平行的線段,那么其中至少有一個懸線。

如果把一個懸線向左右兩個方向盡可能的移動,那么就得到了一個矩形,我們稱它為懸線對應的矩形。

懸線對應的矩形不一定是極大子矩形,因為下邊界可能還可以向下擴展。

設計算法:

 

原理:所有懸線對應矩形的集合一定包含了極大子矩形的集合。
通過枚舉所有的懸線,找出所有的極大子矩形。
算法規模:
          懸線個數=(N-1)×M
          極大子矩形個數≤懸線個數

 

具體方法:

設 H[i,j]為點(i,j)對應的懸線的長度。
     L[i,j]為點(i,j)對應的懸線向左最多能夠移動到的位置。
     R[i,j]為點(i,j)對應的懸線向右最多能夠移動到的位置。

 

 

考慮點(i,j)對應的懸線與點(i-1,j)對應的懸線的關系(遞推思想):
 
如果(i-1,j)為障礙點,那么,如圖所示,(i,j)對應的懸線長度1,左右能移動到的位置是整個矩形的左右邊界。
即 H[i,j]=1,
   L[i,j]=0,R[i,j]=m

如果(i-1,j)不是障礙點,那么,如圖所示,(i,j)對應的懸線長度為(i-1,j)對應的懸線長度+1。
即 H[i,j]=H[i-1,j]+1

 

 

•如果(i-1,j)不是障礙點,那么,如圖所示,(i,j)對應的懸線左右能移動的位置要在(i-1,j)的基礎上變化。
                    L[i-1,j]
L[i,j]=max
                    (i-1,j)左邊第一個障礙點的位置        
•同理,也可以得到R[i,j]的遞推式
                        R[i-1,j]
     R[i,j]=min    
                        (i-1,j)右邊第一個障礙點的位置                            
 
優點: 復雜度與障礙點個數沒有直接關系。
缺點:障礙點少時處理較復雜,不如算法1。

代碼實現具體見WC2002 奶牛浴場(算法1)

codevs1159最大全0子矩陣(算法2)

 


 

補圖:

算法1:

 

 

 

 

 

 

s為障礙點總數。

枚舉一個障礙點作為左邊界O(s),然后不斷向后掃得到極大子矩形O(s),總復雜度為O(s^2)。

當1障礙點數較小時,可以使用算法1。


 

算法2(懸線法):

 

 

 

當障礙點較多,n*m較小時,可以用懸線法。

時間復雜度為O(n*m)。

例題:bzoj1057

 

猴似猴塞雷~~

 

2016-08-19 15:02:38


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM