# 演算法設計方法論 ## 1. Dynamic Programming (DP) - **Principle Of Optimality:subsize 的 optimal 解,是原 size optimal 解的一部分。** - Multistage Graph - 找出 $S\rightarrow T$ 的最短距離 - 令 $l_{ij}$ 為 $a_{ij}$ 到 $T$ 的最短距離 - $(l_{31},l_{32},l_{33})\rightarrow(l_{21},l_{22},l_{23})\rightarrow(l_{11},l_{12},l_{13})\rightarrow S$ - 令 $p_{ij}$ 為 $S$ 到 $a_{ij}$ 的最短距離 - $(p_{11},p_{12},p_{13})\rightarrow(p_{21},p_{22},p_{23})\rightarrow(p_{31},p_{32},p_{33})\rightarrow T$ - Optimal Parenthesization - $c(i,j)$ $\text{= i 到 j 的最小 cost}\\=\text{i 到 j 總和}~+~\min\limits_k(~c(i,k)+c(k+1,j)~)$ - 時間複雜度:$O(n^3)$ - Longest Common Subsequence - $L(i,j)$ $=\text{A[ 1 : i ] 和 B[ 1 : j ] 的最小 cost}\\= max\{L(i-1,j), L(i,j-1), L(i-1,j-1)+l_{ij}\}$ - 時間複雜度:$O(mn)$ - 0/1 Knapsack Problem - $f(k,g)$ $\text{= 前 k 個物品,重量限制 g 的最佳 cost}\\=p_kx_k^*+f(k-1,g-w_kx_k^*)$ $~~~~~~~~~~~=max\{f(k-1,g)~,~~p_k+f(k-1,g-w_k)\}$ - 時間複雜度:$O(nM)$,為 pseudo polynomial time - Integer Knapsack Problem - $f(k,g)$ $\text{= 前 k 個物品,重量限制 g 的最佳 cost}\\= max\{p_kx_k+f(k-1,g-w_kx_k)~|~x_k=0,1,...,g/w_k~\}$ $~~~~~~~~~~~=max\{f(k-1,g)~,~~p_k+f(k,g-w_k)\}$ - 時間複雜度為$O(nM)$,為 pseudo polynomial time - Traveling Salesman Problem - $L(i,S)$ $\text{= 從 i 出發,經過 S 所有元素再回到點 1}\\=min_{j\in S}\{d_{ij}+L(j,S-\{j\})\}$ - 時間複雜度為$O(n2^n)$ - Maximum Weight Independent Set In Tree - $M(i)$ $\text{= 選了節點 i 的最大 cost}\\=w(i)+\sum M'(j)$ - $M'(i)$ $\text{= 不選節點 i 的最大 cost}\\=\sum max(M(j),M'(j))$ - 時間複雜度為$O(n)$ ## 2. Prune-and-Search (P&S) - 時間複雜度可表示為 $T(n) = T((1 - α)n) + p(n)$ - $T(αn)$ 是被刪除的那些子問題 - $p(n)$ 為了刪除不重要的子問題所花的時間 - **Binary Search** - **[Selection Problem](https://ideone.com/uSuPXu)** - 1:把原本數列 5 個一組,共 $\lceil n/5\rceil$ 組, $O(1)$ 算出每一組 median - 2:把 $\lceil n/5\rceil$ 組的 median,挑出 median of median,花時間 $T(n/5)$ - 3:以 MOM 把數列分成三個 set,花時間 $O(n)$ - 4:至少可以刪除掉 $n/4$ 的答案,變成 size 更小的子問題 $T(3n/4)$ - 5:重複直到可以 $O(1)$ 解掉 - 時間複雜度:$T(n)=T(n/5) + O(n) +T(3n/4) = O(n)$ - **The 2-dimensional linear programming problem** - 1:所有限制條件中,如果有垂直線,則更新 $x_l,~x_r$ - 2:根據 $b$ 的正負號,把限制條件分成 $I^+$ 和 $I^-$ - 3:把 $I^+$ 和 $I^-$ 同一組中的線,兩兩配對求交點 - 如果平行的話,一條可以捨去 - 如果交點在 $x_l,~x_r$ 之外,一條可以捨去 - 4:對所有在 $[x_l,x_r]$ 中的交點 $r$,找出 median $x_m$ - 5:找出 $x^*$ 在 $x_m$ 哪一側 - 如果 $x_m = x^*$ 或是 無解,則演算法結束 - 否則更新 $x_l 或 x_r$ - 6:約有 $n/4$ 對可以確定交點和 $x^*$ 相對位置,每一對 prune 掉其中一條線 - 根據講義有六種不同的 case - 7:重複直到可以在 $O(1)$ 直接解出 - 時間複雜度:$T(n) \le T(3n/4) + O(n) = O(n)$ - **The 1-dimensional smallest circle enclosing n points** - 1:把所有點兩兩配成一對,有 $n/2$ 對 - 2:找出每對中垂線和 $y=y_m$ 的交點 - 如果有兩點落在同一條鉛直線上,prune 掉離 $y=y_m$ 比較近的那點。 - 3:找出這些交點的 median $x_m$ - 4:找出 $x^*$ 在 $x_m$ 的哪一側 - 定義 $I$ 為最遠點,看 $I$ 的分布是在兩側或同一側 - 5:約有 $n/4$ 對可以確定中垂線交點和 $x^*$ 相對位置,每一對 prune 掉比較近的點 - 6:重複直到可以在 $O(1)$直接解出 - 時間複雜度:$T(n) \le T(3n/4) + O(n) = O(n)$ - **The 2-dimensional smallest circle enclosing n points** - **給定一條直線,可以在 $O(n)$ 決定 $(x_c,y_c)$ 在直線的哪一側。** - 首先找到該直線上最好的點 $(x^*,y_m)$ - 再根據 $I$ 的分布決定在直線的哪一側 - 只有一點:知道哪一側 - 有 arc 大於 180 度:$(x^*,y_m)$ 就是最佳解 - 沒有 arc 大於 180 度:根據 $p$ 和 $q$ 哪一側點比較近,可知道哪一側 - 1:把所有點兩兩配成一對 $(p,q)$,共 $n/2$ 對 - 2:每對找出中垂線 $L$,共 $n/2$ 條 - 3:每條中垂線算和 $x$ 軸夾角 $α$ - 4:找出所有夾角的 median,$α_m$ - 5:把中垂線依夾角分成兩堆 $L^+,~L^-$,每堆有 $n/4$ 條 - 6:把 $L^+$ 和 $L^-$ 的中垂線兩兩配成一對,共 $n/4$ 對 - 每一對恰好都有一條線角度 $>α_m$,有一條線角度 $<α_m$ - 7:**每一對解出中垂線交點,有n/4點。$\rightarrow$ 標的** - 8:找出斜率為 $α_m$ 且平分中垂線交點的線 $LA$,兩側各有 $n/8$ 點 - 9:決定 $(x_c,y_c)$ 在這條線 $LA$ 哪一邊 - 10:找出鉛直線 $LB$,把 $LA$ 中 $(x_c,y_c)$ 的另一側交點平分,兩側各有 $n/16$ 點 - 11:決定 $(x_c,y_c)$ 在這條線 $LB$ 哪一邊 - 12:現在平面被分成四個區域,把 $(x_c,y_c)$ 的對面區域,挑出不會碰到 $(x_c,y_c)$ 的中垂線,有 $n/16$ 條,每條可以挑出離 $(x_c,y_c)$ 比較近的點,有 $n/16$ 點,把他們 prune 掉 - 13:重複直到可以在 $O(1)$ 直接解出 - 時間複雜度:$T(n) \le T(15n/16) + O(n) = O(n)$ - **Weighted Center of a Tree** (作業) - **給定距離 leaf node $t$ 的點 $x$,可以在 $O(n)$ 決定 center 在 $x$ 哪一側。** - 1:花 $O(n)$ 找出 $T$ 的 Centroid $c$ - 2:花 $O(n)$ 時間,決定 center 在 c 的哪一子樹 - (1)如果鄰居滿足 $r(x)=r_i(x)=r_j(x)$,則這時 $x$ 就是center - (2)否則也可以知道 center 在某個 $T_i(x)$上 - 3:對所有不在 $T_i(x)$ 的 vertex,至少有 $n/2$ 個,把他們配成 $n/4$ 對 - 每一對 $(u,v)$ ,去算出 $t$ 值使得 $w_u(d(u,x)+t) = w_v(d(v,x)+t)$ - 如果 $t$ 不存在,則可以 prune 掉其中一個 vertex - 4:把那些 $t$ 挑出 median $t_m$ 出來 - 5:決定 center 在 $T_i(x)$ 中和 $x$ 距離 $t_m$ 地方的相對位置 - 6:約有 $n/8$ 對可以確定 center 和兩點的相對位置,每一對 prune 掉一個點 - 7:剩下的點仍然會形成一棵樹,整理成 size 為 $7n/8$ 的相同問題 - 8:重複直到可以在 $O(1)$ 解完 - 時間複雜度:$T(n) \le T(7n/8) + O(n) = O(n)$ ## 3. Branch-and-Bound (B&B) - 基本觀念 - **通常是求最大值或最小值的 NP hard 問題,用樹展開所有可能性**: - BFS : 從最上層 state 先展開 - DFS : 從現在 state 先展開 - DFID : DFS 但是每次限定展開層數 - Best First Search : 每一個state量化成分數,透過該分數來選擇 - Hill Climbing : 透過量化資料,決定 DFS 要進入哪個 state - 對一個最大化的問題 - 整棵樹:紀錄目前最大的可行解,也就是 optimal value 的 **lower bound**。 - 每節點:計算 **upper bound**,也就是可以達到的最大值。 - **Branch:** - 選擇最大 upper bound 的節點,把它展開下一層 - **Bound:** - 某節點 **UB** $\le$ 整棵樹 **LB** ,則該節點以下不用展開。 - The 0/1 Knapsack problem - 問題: - $\max 10x_1+10x_2+12x_3+18x_4$ - $2x_1+4x_2+6x_3+9x_4\le15,~~x_i\in\{0,1\}$ - 整棵樹的 lower bound: - 從左到右依序 assign 1 或 0 得到 feasible solution。 - 每個節點的 upper bound: - 用 greedy 的方式從 CP 值最高的物品開始選。 - 例子: - ![](https://i.imgur.com/8HZzOWf.png) - The Traveling Sales Man - 問題: - 給定 $DAG$,求出經過每個點 weight 最小的 path - ![](https://i.imgur.com/JR3lG5u.png) - 觀察: - 每個節點存一個 reduced cost matrix $A$ - 轉換到下一節點時 - 把 $A$ 的 **row** $i$ 和 **col** $j$ 全設成 $\infty$ - 把 $A(j,1)$ 設成 $\infty$ - 計算 reduced cost $r$ - 整棵樹的 upper bound: - 走到 leaf node,或任找 feasible solution,紀錄可行解的最小值。 - 每個節點的 lower bound: - $R\rightarrow S$ - $lb_S=lb_R+A(i,j)+r$ - 也就是 cost matrix 的 reduced cost,至少要花這麼多 weight - The A* Algorithm - 本質上就是一種 best first search,自己定義一個 evaluation function,再展開最有可能的 node。 - **最大值的問題不可以低估,最小值的問題不可以高估** - 以 shortest path 為例: - ![](https://i.imgur.com/dxCg6Qm.png) - 定義 cost function $f(i)$: - $S$ 到 $i$ 距離 $+$ $i$ 的最小向外距離 - 沒有高估 - ![](https://i.imgur.com/CdyFpnh.png) - 第一個回合展開 $v_1$ - ![](https://i.imgur.com/1lCMIBW.png) - 第二個回合展開 $v_2$ 或 $v_4$ ## 4. Divide-and-Conquer (D&C) - 基本觀念 - ![](https://i.imgur.com/qxRV3Df.png) - **Divide**:切割問題成子問題 - **Conquer**:遞迴呼叫相同演算法 - **Merge**:將子問題的答案,組合出原本問題的答案 - 最複雜的分析是 Merge: - 1.$T(n)=2T(n/2)+O(1)=O(n)$ - 2.$T(n)=2T(n/2)+O(n)=O(nlogn)$ - 3.$T(n)=2T(n/2)+O(n^2)=O(n^2)$ - **Merge Sort** - Merge 步驟: - 用 $O(m+n)$ 將兩個 sorted array 合成一個 sorted array。 - $T(n)=2T(n/2)+O(n)=O(nlogn)$ - **Matrix multiplication** - 一般作法: - ![](https://i.imgur.com/fbl9npI.png) - $T(n)=8T(n/2)+O(n^2)=O(n^3)$ - Strassen’s Method: - ![](https://i.imgur.com/zgzo4Fc.png) - $T(n)=7T(n/2)+O(n^2)=O(n^{log_27})$ - **The Convex Hull Problem** - Graham’s Scan - 1.任意挑一個 Convex Hull 內部的點 $x$。 $O(1)$ - 2.將所有點,依照和 $x$ 夾角排序。 $O(nlogn)$ - 3.任意挑一個 Convex Hull 上的點 $y$。 $O(n)$ - 4.依照排序結果從 $y$ 開始,每三點挑出在 convex hull 上的點。 $O(n)$ - 依照中間的點是否再比較近的地方分成兩種 case。 - 時間:$T(n)=O(nlogn)$ - Jarvis’ March - 1.任意挑一個 Convex Hull 上的點 $y$。 $O(n)$ - 2.從 $y$ 開始,逆時針挑出在 convex hull 上的點。 $O(hn)$ - 時間:$T(n)=O(hn)$ - Divide-and-Conquer (基本上是 Graham’s Scan 的延伸) - Divide and Conquer: - 分成兩個相等大小子問題 $A,B$ ,遞迴解決 $CH(A),CH(B)$ - Merge: - 1.任意挑一個 $CH(A)$ 內部的點 $p$。 $O(1)$ - 2.決定 $p$ 是否在 $CH(B)$ 內部。 $O(n)$ - 在內部:直接將兩個 sorted list 合成一個 sorted list。 - 在外部:透過 $CH(B)$ 和 $p$ 相對位置,合成一個 sorted list。 - 找出 $CH(B)$ 中夾角最大和最小的點 $u,v$,看是否都在 $p$ 同一側 - 3.利用 Graham’s Scan ,每三點挑出在 $CH(A\cup B)$ 上的點。 $O(nlogn)$ - 時間:$T(n)=2T(n/2)+O(n)=O(nlogn)$ - **The 2-dimensional closest pair problem** - Presort 所有點 $y$ 座標,得到 $y$ 的順序。(在最一開始) - 1.Divide:依照 $x$ 座標,將點分成相同大小左右兩部分 $L,R$。 - 2.Conquer:$L,R$ 分別去解出最近距離 $d_L,d_R$。 - 3.Merge: - 對於左右的 sorted list $S_L,S_R$,找出距離比 $min(d_L,d_R)$ 還要小的點對。 - 方法一:使用兩個指標,比較複雜。 - 方法二:先 merge 成一個 sorted list,每個點只要比較 6 個點。 - 時間:$T(n)=2T(n/2)+O(n)=O(nlogn)$ - **The Iso-Oriented Line Segment Intersection Problem** - Presort 所有垂直線兩端點 $y$ 座標,得到 $y$ 的順序。(在最一開始) - **標的:垂直線,水平線的端點。** - 1.Divide:依照 $x$ 座標,將標的分成相同大小左右兩部分 $L,R$。 - 2.Conquer:$L,R$ 分別紀錄: - ![](https://i.imgur.com/SkiGbH4.png) - type 1,2,3 的 Intersection Point。 - 右邊界上水平線的照 $y$ 順序 $\tilde{R}$ - 左邊界上水平線的照 $y$ 順序 $\tilde{L}$ - $V$:垂直線照 $y$ 排序。 - 3.Merge: - 給定:$\tilde{L}_L,\tilde{R}_L,\tilde{L}_R,\tilde{R}_R$ - $\tilde{L}\tilde{R}\leftarrow\tilde{R}_L\cap\tilde{L}_R$ - $\tilde{L}\leftarrow\tilde{L}_L+(\tilde{L}_R-\tilde{L}\tilde{R})$ - $\tilde{R}\leftarrow\tilde{R}_R+(\tilde{R}_L-\tilde{L}\tilde{R})$ - 給定 $V_L,V_R$ 為左右兩部分垂直線,找出 Intersection Point。 - $V_L$ 和 $\tilde{L}_R-\tilde{L}\tilde{R}$ 的 Intersection Point。 - $V_R$ 和 $\tilde{R}_L-\tilde{L}\tilde{R}$ 的 Intersection Point。 - 時間: - $T(n)=2T(n/2)+O(n)=O(nlogn)$ - 總共 $=T(n)+O(nlogn)+O(s)=O(nlogn+s)$ - **Voronoi Diagram Construction** - 問題定義與介紹: - 平面上給定 $n$ 個點,找出每個點 $i$ 的地盤 $V(i)$。 - 每一個 Voronoi Diagram ,有一個對應的 Delaunay graph。 - 如果沒有四點共圓,則對應的為 Delaunay triangulation。 - 定理:每一個 $n$ 點的 Voronoi Diagram,最多只有 $2n-4$ 個點和 $3n-6$ 個邊。 - 定理:一個 Voronoi Polygon $V(i)$ 是 unbounded $\iff$ $i$ 在圓圖的 convex hull 上。 - 一個 Voronoi Diagram 包含以下資料(結構): - Voronoi vertices 的點座標 - Voronoi edges 連結那些 Voronoi vertices - Voronoi edges 對應原圖的兩點 - 原圖每點的照順時針序的每個 Voronoi edges - 分治解法: - 1.Divide:依照 $x$ 座標,將點分成相同大小左右兩部分 $L,R$。 - 2.Conquer:$L,R$ 分別去解出 $VD(L),VD(R)$。 - 3.Merge:找出 dividing line $P$,使得到 $L$ 和 $R$ 一樣近,並刪除 $VD(L),VD(R)$ 超過 $P$ 的部分。 - ![](https://i.imgur.com/cj2vRAo.png) - 定理:dividing line $P$ 是 $y$ 的連續函數,且頭尾是兩條射線。 - 找 $P$ 的兩個步驟: - Step 1:找出頭尾兩條射線 - 射線必定是 $CH(L\cup R)$ 上,一個橫跨 $L$ 和 $R$ 的邊的中垂線 - 1.我們透過 $VD(L),VD(R)$ 去找 $CH(L),CH(R)$ - 2.透過 $VD(L),VD(R)$ 合成 $CH(L\cup R)$ 並找出對應的邊及中垂線。 - Step 2:透過 zigzag walk 找到 $P$ - 觀察: - $P$ 總是往下走 - 當碰到 $VD(L)$ 的邊時,要往右轉。 - 當碰到 $VD(R)$ 的邊時,要往左轉。 - 1.檢查 $P$ 現在在 $VD(L)$ 和 $VD(R)$ 離哪個點最近 - 2.比較會先碰到 $VD(L)$ 的邊或是 $VD(R)$ 的邊。 - 時間:$T(n)=2T(n/2)+O(n)=O(nlogn)$ - 其他常見應用: - 1.All Nearest Neighbor 最近鄰居 - 問題:給定平面上 n 個點,找出每個點的最近鄰居集合。 - 一個點 $i$ 和其最近鄰居,定義了 $V(i)$ 的其中一邊。 - 因此給定 $VD(G)$ ,則可以在 $O(n)$ 解完此問題。 - 2.Nearest Beighbor Search Problem - 問題:給定平面上 n 個點。每次 query 點 $x$,找出 $x$ 的最近鄰居集合。 - 1.先花 $O(nlogn)$ 時間,$O(n)$ 空間,建構 Voronoi Diagram。 - 2.每次花 $O(logn)$ 時間,尋找點 $x$ 位在哪一個 Voronoi Polygon 內部。 - 3.Euclidean Minimum Spanning Tree Problem 平面上找最小生成樹 - Kruskal:$O(n^2)$ - Prim:$O(n^2logn)$ - 定理:每個 Euclidean Minimum Spanning Tree 都是 Delaunay graph 的子圖。 - 定理:Planar Graph 的 MST 問題可以在 $O(n)$ 解完。 - 1.花 $O(nlogn)$ 時間,建構 Voronoi Diagram。 - 2.花 $O(n)$ 時間,建構 Delaunay Graph。 - 3.花 $O(n)$ 時間,找 Delaunay Graph 上的 Minimum Spanning Tree。