算法設計與分析2 - 嵌套箱問題

2、嵌套箱問題
2 、一個d 維箱(x1,x2,...,xn)嵌入另外一個d 維箱 (y1,y2,...,yn) 是指存在1,2,…,d 的一個排列π,使得 xπ(1)<y1 ,xπ(2) <y2, ... , xπ(d)<yd
1)  證實上述箱嵌套關係具備傳遞性;
2)  試設計並實現一個貪心算法,用於肯定一個d維箱是否可嵌入另外一個d維箱;
3)  給定由n d 維箱組成的集合 { B1,B2,B3,...,Bn} ,試設計並實現一個貪心算法找出這n d維箱中的一個最長嵌套箱序列,並用nd 描述算法的計算時間複雜性。
 
1)  箱嵌套關係的傳遞性
證實:
設有 3 d 維箱 B1(x1 , x2 , ... , xd) B2 (y1 , y2 , ... , yd) B3(z1 , z2 , ... , zd) B1 可嵌入 B2 B2 可嵌入 B3
B1 可嵌入 B2 ,則存在排列π使得:
xπ(1) < y1 xπ(2) < y2 ,..., xπ(d) < yd        —— 1
B2 可嵌入 B3 ,則存在排列θ使得:
yθ(1) < z1 yθ(2) < z2 ,..., yθ(d) < zd        —— 2
   1 式可得:
xθ(π(1)) < yθ(1) xθ(π(2)) < yθ(2) ,..., xθ(π(d)) < yθ(d)  —— 3
2 3 可得:存在排列 λ = θπ 使得:
xλ(1) < z1 xλ(2) < z2 ,..., xλ(d) < zd
根據d維箱的定義可得, B1 可嵌入 B3 。所以,嵌套箱關係具備傳遞性。
 
2)  d 維箱的嵌套關係
   貪心選擇性質 :
對於d維箱X (x1 , x2 , ... , xd),Y (y1 , y2 , ... , yd), 排列 π θ 是分別使 X Y 非遞減有序的排列,有以下 結論:XY(表示X可嵌入Y)的充要條件是,對任意1id x π(i) < yθ(i)
 
證實 :
      a. 充分性 :
對任意1id x π(i) < yθ(i) 時,令 λ = πθ-1, 那麼
x λ(i) = x π(θ -1 (i)) < yθ(θ-1 (i)) = yi 即存在一個排列 λ 使得對於 任意1id x λ(i) < yi ,因此 X Y
   b. 必要性:
用數學概括法證實。
當維數爲1,XY 可得 x1 < y1 那麼 x π(1) < yθ(1) 成立
假設維數爲 d 時,結論成立,即 : XY時,對於任意1id,有 x π(i) < yθ(i) 那麼當維數爲 d + 1 時, 對於任意1id+1XY,則存在 λ 使得 :
xλ(1) < y1 xλ(2) < y2 ..., xλ(d) <yd xλ(d+1) <yd+1  —— 1
先觀察 1 式前 d , xλ(1) < y1 xλ(2) < y2 ..., xλ(d) <yd
由假設可知,對任意1id,有存在排列 π θ 使得 x π(i) < yθ(i)
:
x π( 1) x π( 2) ... x π( d)  —— 2
y θ( 1) y θ( 2) ... y θ( d) —— 3
x π(1) < yθ(1) x π(2) < yθ(2) ,..., x π(d) < yθ(d)  —— 4
此時, π θ 只對 1 式前 d 項進行排列,並不包含 xλ(d+1) yd+1 。能夠將 xλ(d+1) 按大小順序插入到 2 ( 設插入位置爲 j) ,從而有新的排列 π’ 使得 xi ( 1 id+1 ) 非遞減有序。
同理,也有 θ’ 使得 yd+1 按大小順序插入到 3 式後 ( 設插入位置爲 k) yi ( 1 id+1 ) 非遞減有序。
由於 xλ(d+1) <yd+1 易知 j k
j = k 時,由於 x m ym ( 1 md+1 ) 的對應位置都沒有變, 顯然 x π’(i) < yθ’(i) ( 1 id+1 ) 所證結論成立。
j<k 時, x1<y1 x2<y2 ,..., xj<xj+1<yj xj+1<xj+2< yj+1 ,..., xk-1<xk< yk -1 xk<yk -1 < yk xk+1<y k+1 ,..., xd+1< y d+1
, 對任意1id+1 x π’(i) < yθ’(i) 所證結論成立。
命題得證。
 
   算法實現
由上面所得結論,對兩個 d 維箱進行排序後,只要判斷排序後兩個 d 維箱的嵌套關係就能夠得出結果。
-----------------------------------------------------------------------------------------
求兩個箱子的嵌套關係的僞代碼 :
返回 1 表示 X 嵌套 Y( Y X)
返回 –1 表示 Y 嵌套 X( X Y)
返回 0 表示 X Y 之間無嵌套關係
NEST(X , Y , d):
      Sort(X)     ▹對數組所表示的 d 維箱 X Y 進行排序  
Sort(Y)
 
if X[0] > Y[0]
  then for i ← 1 to d – 1
        do if X[i] <=Y[i]
                        then return 0
           return 1    
  else for i ← 0 to d – 1
        do if X[i] >=Y[i]
                     then return 0
           return –1
--------------------------------------------------------------------------------------
   時間複雜度分析
NEST() 的主要時間消耗在於排序,使用快速排序時, NEST() 的時間複雜度爲 : O(d lgd)
 
   算法測試
對應的算法實現 Java 源文件爲 NestedBox.java
輸入: X(1,6,2,5,9) Y(7,4,8,19,32)
輸出 :  Y 嵌套 X
 
3)  最長嵌套箱序列
   算法思想
n d 維箱之間的關係用一棵樹來表示,其中可嵌套其它箱子的箱子爲父節點,被嵌套的箱子做爲孩子節點,無嵌套關係的節點爲兄弟節點。這樣就一個 d 維箱的深度值就是在這棵樹中的深度。
深度值的遞歸定義以下 :

只要找出深度最大的節點,而後遞歸地輸出它嵌套的箱子,結果就是最長嵌套箱序列。
   貪心選擇性質
假設最長 d 維箱序列的一個最優解是 B1 , B2 , …,Bk  (k>1), 其對應的深度值分別爲 H1, H2 , …, Hk (H1 > H2…> Hk)
a. H1 爲最大的深度值,則說明問題的最優解以一個貪心選擇開始。
b. H1 不是最大的深度值,不妨設 H1<Hj (1<j k) 。但 B1 嵌套 Bj 可得 H1 >Hj 。與假設矛盾。因此 H1 爲最大的深度值,這說明問題的最優解以一個貪心選擇開始。
   最優子結構性質
設嵌套序列 B1 , B2 , …,Bk  (k>1) 是問題的一個最優解,各個箱子的深度值爲 H1, H2 , …, Hk (H1 > H2…> Hk) 。由貪心選擇性質可知 H1 爲最大深度值,其他箱子組成的序列 B2 ,B3 , …,Bk  (k>1) 是在全部箱子中去掉 B1 及與其具備相同深度值的箱子後,在剩下的箱子中查找最長嵌套箱序列的一個最優解。所以,最長嵌套箱序列問題具備最優子結構性質。
   算法實現
--------------------------------------------------------------------------------------
求最長嵌套箱序列的僞代碼 :
B 爲存放 n d 維箱的二維數組
Longest(B , n , d):
A 存放各箱子嵌套關係的二維數組 , 下標從 0 開始 , 列數爲 n+1.
A[i,n] 表示箱子 i 的深度值
 
      初始化 A 數組
      for i ← 0 to n
           do A[i , n] ← 0
      計算嵌套關係
      for i ← 0 to n – 1
           do for j ← i+1 to n – 1
                    do A[i , j] ← nest(B[i] , B[j] , d)
                        A[j , i] ← – A[i , j]
     遞歸地修改嵌套的深度值
      for i ← 0 to n – 1
           do for j ← 0 to n – 1
                  if A[i , j] = – 1
                    then addHeight(A , n , i , j)
      查找深度值最大的箱子做爲首嵌套箱
      maxBoxIndex findMax()
      輸出最長嵌套箱序列
      trace(maxBoxIndex)
--------------------------------------------------------------------------------------
遞歸地修改嵌套箱的深度值
addHeight(A , n , i , j):
      if A[i , n] = A[j , n]
        then A[j , n] A[j , n] + 1
                 for k ← 0 to n – 1
                   do if A[j , k] = – 1
                          then addHeight(A , n , j , k)
--------------------------------------------------------------------------------------
查找深度值最大的箱子做爲首嵌套箱
findMax(A , n):
      max ← A[0 , n]
      maxBoxIndex ← 0
     
      for i ← 0 to n – 1
        do if A[i , n] > max
               then max ← A[i , n]
                        maxBoxIndex ← i
      return maxBoxIndex
--------------------------------------------------------------------------------------
根據深度值最大的箱子 , 輸出最長嵌套箱序列
trace(n , maxIndex):
      while A[max][n] > 0
        do seq ← (max+1) + 「 」 + seq
             m ← 0
             for i ← 0 to n – 1
               do if A[max , i] = 1 and A[i , n] >=m
                       then m ← A[i , n]
                                   temp ← i
             max ← temp
      seq ← (max+1) + 「 」 + seq
      print seq
--------------------------------------------------------------------------------------
   時間複雜度分析 :
     算法的主要時間消耗在於 Longest() 計算嵌套關係的時候,其中 nest() 算法的時間複雜度爲 O(d lgd) 。因此總時間複雜度爲 : O(n2 d lgd)
 
   算法測試 :
相應的算法實現文件爲 LongestNestedBox.java
輸入數據 : (8 6 維箱 )
{5, 2, 20, 1, 30, 10},{23, 15, 7, 9 ,11, 3},
{40 ,50 ,34 ,24, 14, 4},{9 ,10, 11 ,12, 13, 14},
{31, 4 ,18, 8 ,27, 17},{44, 32, 13, 19 ,41, 19},
{1 ,2, 3 ,4 ,5, 6},{80, 37 ,47 ,18 ,21, 9}
輸出數據 : ( 輸出數據中的數字表明按順序輸入的箱子,編號從 1 開始 )
最長嵌套箱序列 :7 2 5 6
相關文章
相關標籤/搜索