貪婪演算法
This presentation is the property of its rightful owner.
Sponsored Links
1 / 104

貪婪演算法 與 動態規劃演算法 PowerPoint PPT Presentation


  • 238 Views
  • Uploaded on
  • Presentation posted in: General

貪婪演算法 與 動態規劃演算法. 短視近利與深謀遠慮 江振瑞. 3.1 貪婪演算法基本概念. 貪婪解題策略. 貪婪演算法 ( greedy algorithm) 使用 貪婪策略 (greedy strategy) 解決問題。 假設一個問題可以藉由一系列的選擇 ( 或決策 ) 來解決,貪婪演算法的特性為每一次選擇皆採取 區域最佳解 (locally optimal solution) ,而透過每一個區域最佳解最後綜合成為 全域最佳解 (globally optimal solution) 而將問題解決。

Download Presentation

貪婪演算法 與 動態規劃演算法

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


6459115

貪婪演算法與動態規劃演算法

短視近利與深謀遠慮

江振瑞


6459115

3.1 貪婪演算法基本概念


6459115

貪婪解題策略

  • 貪婪演算法(greedy algorithm)使用貪婪策略(greedy strategy)解決問題。

  • 假設一個問題可以藉由一系列的選擇(或決策)來解決,貪婪演算法的特性為每一次選擇皆採取區域最佳解(locally optimal solution),而透過每一個區域最佳解最後綜合成為全域最佳解(globally optimal solution)而將問題解決。

  • 換句話說,貪婪演算法一步步地建構出一個問題的完整解答。其每一步都藉由貪婪解題策略選擇當下最好的部份解答加入完整解答中以解決問題。


6459115

使用貪婪解題策略的演算法

  • 背包(Knapsack)演算法

  • Huffman編碼演算法

  • Kruskal最小含括樹演算法

  • Prim最小含括樹演算法

  • Dijkstra最短路徑演算法


6459115

3.2 背包演算法


6459115

背包演算法背景介紹

  • 背包演算法(knapsack algorithm)使用貪婪解題策略解決背包問題(knapsack problem)或稱為零碎背包問題(fractional knapsack problem)

  • 以下我們先定義背包問題


6459115

定義 -- 背包問題

  • 給定一個最大載重容量(capacity)為m的背包,以及n個可以放入背包的物品,其中第i個物品的重量為wi>0,價格為pi>0

  • 目標: 找出x1,…,Xn以最大化

  • 限制條件為

    其中 0xi1, 1 i n


6459115

背包演算法

Algorithm 背包演算法

Input: 背包的最大容量m,以及可以放入背包的n個物品的非負重量wi與價格pi

Output: 介於0與1之間的x1,…,xn分別代表第1個,…,第n個物品放入背包中的零碎部份。可以最大化 ,並且滿足 。

1: 將pi/wi由大至小排序。

2: 根據此排序來將物品依序盡可能地放入背包中,直至背包容量m用完為止。


6459115

背包演算法時間複雜度

  • 行1: 依pi/wi由大至小排序:O(n log n)

  • 行2: 將物品依序放入背包:O(n)

    總時間複雜度:O(n log n)


6459115

背包演算法範例

  • 給定:

    n = 3, m = 5, (w1, w2, w3) = (1, 2, 3)

    (p1, p2, p3) = (20, 60, 45)

  • 貪婪策略解答:

    p1/w1 = 20/1 = 20

    p2/w2 = 60/2 = 30

    p3/w3 = 45/3 = 15

    最佳解:x2 = 1, x1 = 1, x3 = 2/3

    最大總價值:601+201+45(2/3)=110


6459115

定義 -- 0/1背包問題

  • 給定一個最大載重容量(capacity)為m的背包,以及n個可以放入背包的物品,其中第i個物品的重量為wi>0,價格為pi>0

  • 目標: 找出x1,…,Xn以最大化

  • 限制條件為

    其中 xi=0 or xi=1, 1 i n


6459115

0/1背包演算法範例

  • 給定:

    n = 3, m= 5, (w1, w2, w3) = (1, 2, 3)

    (p1, p2, p3) = (20, 60, 45)

  • 貪婪策略解答:

    p1/w1 = 20/1 = 20

    p2/w2 = 60/2 = 30

    p3/w3 = 45/3 = 15

    解答:x2 = 1, x1 = 1, x3 = 0

    總價值:601+201+450=80

    • 最佳解:x1 = 0, x2 = 1, x3 = 1

      總價值:200+601+451=105


6459115

背包演算法與0/1背包演算法範例圖示


6459115

3.3 Huffman編碼演算法


Huffman

Huffman編碼

  • 字元編碼(character coding)可以分為

    • 固定長度編碼: 如ACSII、Unicode

    • 可變長度編碼: Huffman code

  • Huffman編碼以字首碼(prefix code)方式達到字元編碼最佳資料壓縮(optimal data compression)

    • 字首碼 (prefix code):任何字元編碼一定不是其他字元編碼的字首(prefix)。

    • 可以使用二元樹來呈現,達到簡單編碼(encoding)與解碼(decoding)的功能。


Huffman1

Huffman編碼範例

  • 假設給定一個僅用到a, b, c, d, e五個字元的文件,現在欲針對五個字元進行編碼,以下是可能的固定長度編碼與可變長度的Huffman字首碼。

  • 字首碼讓出現頻率較高字元的編碼較短,以達到使用最少位元就可以將所有資料儲存的目標。


6459115

對應不同編碼的樹及其成本

Cost(T)=3

Cost(T)=2.17


Huffman2

Huffman編碼演算法

Algorithm Huffman編碼演算法

Input: 字元集合C與每個字元的出現頻率f

Output: Huffman編碼樹

1.n  |C| //C: the set of n characters

2.Q  C//Q: 優先佇列,以字元頻率為優先次序

3.fori 1to n – 1 //n個字元(節點)欲合併成一個節點,每迭代合併一次可少一節點

4. 配置一個新的樹節點u

5.u.left x  GetMin(Q)

6.u.right y  GetMin(Q)

7.u.f x.f + y.f

8. Insert u into Q

9.returnGetMIN(Q) 作為Huffman編碼樹的樹根


Huffman3

Huffman編碼演算法時間複雜度

  • 行2: O(n)建立優先佇列Q

  • 行3-8: for迴圈一共執行n-1次,而且迴圈中的優先佇列操作均為O(log n)複雜度,因此整個迴圈具有O(n log n)的複雜度

    總時間複雜度:O(n log n)


6459115

Huffman編碼演算法的執行範例


6459115

Huffman編碼演算法的執行範例(續)


6459115

Huffman編碼演算法的執行範例(續)


6459115

Huffman編碼演算法的執行範例(續)


6459115

Huffman編碼演算法的執行範例(續)

(4)


6459115

3.4 Kruskal最小含括樹演算法


6459115

最小含括樹

  • 最小含括樹(Minimum Spanning Tree, MST)可以定義在歐式空間(Euclidean space)或者一個圖(graph)上。

  • 給定一個加權連通無向圖(weighted connected undirected graph)G = (V, E)

  • 含括樹(spanning tree)H= (V, T), T  E, 是一個無向樹(undirected tree),它是G的子圖,包含G的所有節點

  • 最小含括樹MST是一個擁有最小(minimum)總權重(weight)或總成本(cost)的含括樹。


6459115

最小含括樹範例

  • 圖G的最小含括樹(非唯一)

  • 一個圖G


Kruskal

Kruskal最小含括樹演算法概念

  • Kruskal最小含括樹演算法是一個貪婪演算法(greedy algorithm)

  • 它採取貪婪解題策略產生給定圖G=(V, E)的最小含括樹H=(V, T),每次都是挑選最小成本且不形成cycle的邊加入目前的最小含括樹的邊集合T之中

  • 因為n個節點的樹具有n-1個邊,因此,經過n-1次邊的挑選之後,就可以形成累積成本最小的含括樹。


Kruskal1

Kruskal最小含括樹演算法

Algorithm Kruskal最小含括樹演算法

Input: 無向加權圖G=(V, E),其中|V|=n

Output: G的最小含括樹(MST)H=(V, T)

  • T← //T為MST的邊集合,一開始設為空集合

  • while T包含少於n-1個邊 do

  • 選出邊(u, v),其中(u, v)E,且(u, v)的加權(weight)最小

  • E←E-(u, v)

  • if ( (u, v)加入T中形成循環(cycle) ) then 將(u, v)丟棄

  • else T←T(u, v)

  • return H=(V, T)


Kruskal2

Kruskal最小含括樹演算法執行範例


Kruskal3

Kruskal最小含括樹演算法討論

Q: 我們如何檢查加入新的邊是否會形成循環?

A: 使用 集合 (SET) 尋找與 聯集 (UNION)操作

  • 使用 集合 (SET) 與聯集 (UNION)操作。

  • 考慮樹的節點集合:一開始產生n個包含單一節點的集合;也就是說若V={v1,…,vn} ,則產生{v1}, {v2},…,{vn}

  • 加入邊(u, v)是否會形成循環:找出u,v所屬的集合,若 u, v 在相同的集合, 則加入邊(u, v)會形成循環。反之,若uS1 , vS2 ,而且 S1S2則加入邊(u, v)不會形成循環,此時應對 S1與 S2進行聯集操作。


Kruskal4

Kruskal演算法的時間複雜度

  • 時間複雜度: O(|E| log|E|)

排序

: O(|E| log|E|)

行2-6 迴圈 (幾乎每個邊都要檢查)O(|E|)

O(|E| log|E|)

找出元素所在的集合 O(log |V|)

: O(|E| log |V|)

|E|  |V|2

聯集兩集合 O(log |V|)

=O(|V|2log |V|)

=O(n2 log n)


6459115

3.5 Prim最小含括樹演算法


6459115

Prim最小含括樹演算法概念

  • Prim最小含括樹演算法是一個貪婪演算法(greedy algorithm)。

  • 它採取貪婪解題策略產生給定圖G=(V, E)的最小含括樹H=(V, T)。此演算法先隨意挑一個節點加入集合X中,此後每次都挑選一個一端的節點在X中,而另一端的節點在(V-X)中的最小成本的邊。如此,可保證將所挑選的邊加入T之後不會形成循環(cycle),這代表H=(V, T)是一棵樹(tree)。

  • 等挑完n-1個邊之後,H=(V, T)就是最小含括樹(MST)。


6459115

Prim最小含括樹演算法

Algorithm Prim最小含括樹演算法

Input: G=(V, E)為無向加權圖,其中|V|=n

Output:G的最小含括樹(MST)H=(V, T)

  • T← //T為MST的邊集合,一開始設為空集合

  • X←{v} //隨意選擇一個節點v加入集合X中

  • while T包含少於n-1個邊 do

  • 選出(u, v)E,其中uX且vV-X,且(u, v)的加權(weight)最小

  • T←T(u, v) //(u, v)是一個邊

  • X←X{v}

  • return H=(V, T)


6459115

Prim最小含括樹演算法執行範例


6459115

Prim最小含括樹演算法時間複雜度

  • 總時間複雜度: O(n2),因為

    • 外層的while迴圈(行3-6): n-1  O(n)

    • 內層迴圈(行4): 在(u,v)中選擇最小權重,其中u屬於X,v屬於V-X  O(n)(藉著使用Prim提出的兩個向量C1和C2)(Ref: R. C. Prim, “Shortest connection networks and some generalizations,” Bell System Technical Journal, 36(1389–1401), 1957.)

  • 比較: 如果 |E|<<n2,則採用Kruskal演算法(複雜度O(|E| log|E|)效能較佳


6459115

3.6

Dijkstra最短路徑演算法


6459115

圖的最短路徑

  • 由圖(graph)中的某個節點(vertex or node)v到圖中的另一節點u,若v到u之間存在一條路徑(path),則路徑中所經過的邊(edge)的權值(weight)的總合稱為路徑的成本(cost)或距離(distance)。所有路徑中具有最小成本的稱為最短路徑(shortest path)。

  • 由於最短路徑具有許多應用,因此有許多求取最短路徑的演算法,著名的演算法包括:

    (1) Dijkstra演算法(使用貪婪解題策略)

    (2) Bellman-Ford演算法(使用動態規劃解題策略)

    (3) Floyd-Warshall演算法(使用動態規劃解題策略)


6459115

Dijkstra最短路徑演算法設計者

  • E. W. Dijkstra(1930年5月11日-2002年8月6日)生於荷蘭鹿特丹

  • 在1972年獲得圖靈獎(Turing Award)

  • 2002年,Dijkstra獲得了ACM PODC (Principles of Distributed Computing) 最具影響力論文獎(Influential Paper Award),以表彰他在分散式計算(distributed computing)領域中關於自我穩定(self stabilization)計算模式的貢獻。為了紀念他,這個每年一度獎項也在此後被更名為Dijkstra獎(Dijkstra Prize)

Source: http://en.wikipedia.org/wiki/Edsger_W._Dijkstra

Creative Commons Attribution-Share Alike 3.0 Unported

Author:HamiltonRichards


Dijkstra

是喝咖啡時20分鐘想出的發明

Dijkstra最短路徑演算法

  • “One morning I was shopping in Amsterdam with my young fiancée, and tired, we sat down on the café terrace to drink a cup of coffee and I was just thinking about whether I could do this, and I then designed the algorithm for the shortest path. As I said, it was a 20-minute invention. In fact, it was published in 1959, three years later.”

    Thomas J. Misa (Editor), "An Interview with Edsger W. Dijkstra," Communications of the ACM 53 (8): 41–47, 2010.

Attribution 2.0 Generic (CC BY 2.0) Elliott Brown

Source: https://www.flickr.com/photos/ell-r-brown/14165662691/in/photolist-


Dijkstra1

Dijkstra最短路徑演算法介紹

  • Dijkstra演算法: Dijkstra演算法屬於求取單一(single)源(source)節點至全部(all)終(destination)節點的單源點至全終點之一至全(one-to-all)最短路徑演算法。

  • Dijkstra演算法只能用在所有的邊都是非負邊(non-negative weighted edge)的圖。因為負邊有可能產生負循環,因而無法產生正確的最短路徑,而Dijkstra演算法並無法檢查給定的圖是否有負循環。

  • Dijkstra最短路徑演算法採用貪婪策略解決問題,每次都挑選一個目前可以由源節點抵達距離(累積邊加權)最小的節點往外調整其鄰居節點的最短路徑距離。在經過n次(n為節點個數)的節點選擇之後,則所有的節點都可以求得由單一源節點可以抵達的最短路徑距離。


Dijkstra2

Dijkstra最短路徑演算法

Algorithm Dijkstra最短路徑演算法

Input:給定一個非負加權有向圖(non-negative weighted digraph)G=(V, E),及一個來源(source)節點s。G各邊的加權值以w[x][y]表示,其中x 及y為邊的二個節點。

Output:對每一個節點u而言,傳回一個由s到u的最短路徑距離(累積邊加權)d[u]。

  • d[s]←0; d[u]←∞ for each u≠s

  • 將每一個節點加入優先佇列Q

  • while Q≠ do

  • 自Q中移出具有最小d[u]值之節點u

  • for 每一個與u相鄰之節點xdo

  • if d[x]>d[u]+w[u][x] then

  • d[x]←d[u]+w[u][x]

  • return d


Dijkstra3

Dijkstra最短路徑演算法如何記錄所有的路徑?

  • 我們將d[u]以加中括號的方式標記在每一個節點旁,使用下圖說明Dijkstra演算法求節點A到每一個節點最短路徑的過程。

  • 若要讓Dijkstra演算法也能夠求出每一條最短路徑所經過的每一個節點,則我們要將每一節點在最短路徑中的前一節點紀錄下來,其作法為增加一個陣列p(代表predecessor,前行者)來記錄最短路徑中的每一個節點的前一節點。並將Dijkstra演算法之if敘述修改如下:

  • if (d[x]>d[u]+w[u][x]) then

    d[x]←d[u]+w[u][x]

    p[x]←u //此敘述為新加入者,代表在最短路徑中節點x的前一節點為u


Dijkstra4

Dijkstra演算法執行範例


Dijkstra5

Dijkstra最短路徑演算法複雜度

假設G一共有n個節點,m個邊(也就是|V|=n, |E|=m)

  • 行2將每一個節點加入優先佇列Q,因此Q具有n個元素

  • 行3的while迴圈每次迭代會自Q中次移出一個節點,因此會執行n次迭代

  • 行4使用O(log n)時間自Q中移出最小d[u]值之節點u

  • 行5的for迴圈在整個演算法的執行過程中一共執行m次迭代

  • 行7使用O(log n)的時間根據新的d[u]值更新u在Q中的位置(先刪除u在新增u

    因此總時間複雜度為O((n+m) log n)=O( (|V|+|E|) log |V|)


6459115

3.7

動態規劃演算法基本概念


6459115

動態規劃解題策略

  • 動態規劃演算法(dynamic programmingalgorithm)使用動態規劃策略(dynamic programming strategy)解決問題。它將原問題分解成一系列子問題(subproblems),並依序解決子問題來解決原問題。為避免一再地解重複的子問 題,一旦解出子問題的解答(solution),即會將其存在表格(或陣列)中。當需要用到某一子問題的解答時,即直接從表格中取出其解答以節省計算時間,是一個「系統化」的、「節省不必要計算」的、「以空間換取時間」的演算法。

  • 一個動態規劃演算法一般先解出最簡單的子問題,並以一定的程序持續運行直至求出原問題解答為止。


6459115

最佳解原則

最佳解原則(Principle of Optimality):

  • 假設我們可以將一個問題P分解為一系列的子問題P1 , P2, …,Pn-1, Pn,而必須作出一系列的決策 D1, D2, …,Dn-1, Dn

  • 若這一系列的決策 D1, D2, …,Dn-1, Dn可以產生P的最佳解,則針對於完成第i個到第j個(1ijn)連續決策後所產生的新狀態而言(也就是在新狀態解決子問題P1,…,Pi-1,Pj+1,…,Pn) ,其他的決策相依於這個狀態必定也能產生最佳解。


6459115

動態規劃與貪婪演算法之比較

  • 比較:

    二者都是透過一系列的決策以解決問題,但是有以下的不同點:

    • 在貪婪演算法中,任何決策都是獨立(independent)的,都只要考慮區域最佳解(locally optimal)。這些區域最佳解最後會加成為全域最佳解(globally optimal solution)。

    • 在動態規劃演算法中,決策是相依的(dependent)。相依於第i個到第j個(1ijn)決策所產生的狀態(子問題)而言,其他的決策必定也是最佳的,藉以求得全域最佳解(globally optimal solution)。


6459115

使用動態規劃解題策略的演算法

  • Bellman-Ford最短路徑演算法

  • Floyd-Warshall最短路徑演算法

  • 多階圖最小成本路徑演算法

  • 最長共同子序列演算法

  • 矩陣鏈乘積演算法


6459115

3.8 Bellman-Ford最短路徑演算法


Bellman ford

Bellman-Ford最短路徑演算法介紹

  • 與Dijkstra演算法相同,Bellman-Ford演算法也是屬於求取單一源節點至全部終節點的一至全最短路徑演算法。

  • 但是與Dijkstra演算法不同的是,Bellman-Ford演算法可以檢查圖是否有負加權循環(cycle),因此在具有負加權(negative weight)邊的圖也可以正確的執行。


Bellman ford1

Bellman-Ford最短路徑演算法介紹(續)

  • Bellman-Ford最短路徑演算法採用動態規劃策略解決問題。一開始在第1次迭代先求出所有屬於1-邊路徑(1-edge path)的最短路徑,並將其最短路徑距離儲存在陣列中;然後基於這個儲存結果在第2次迭代針對每個邊,由始點(startingnode)往外調整到止點(endingnode)的最短路徑距離,可以得出所有屬於2-邊路徑(2-edge path)的最短路徑;…。依此類推則在第n-1次迭代可以求出所有屬於(n-1)-邊路徑((n-1)-edge path)的最短路徑。因為具n個節點的圖最長的路徑具有n-1個邊,因此第n-1次迭代求出的路徑已經是最終的正確結果了。


Bellman ford2

Bellman-Ford最短路徑演算法

Algorithm Bellman-Ford最短路徑演算法

Input: 給定一個加權有向圖(weighted digraph)G=(V, E),及一個來源(source)節點s。G各邊的加權值以w[x][y]表示,其中x 及y為邊的二個節點。

Output: 對每一個頂點u而言,傳回一個由s到u的最短路徑距離(累積邊加權)d[u]。

  • d[s]←0; d[u]←∞ for each u≠s

  • for i←1 to |V|-1 do

  • for 每一個G的邊(u, x)do

  • if d[x] > d[u] + w[u][x] then

  • d[x]← d[x] + w[u][x]

  • for 每一個G的邊(u, x) do //檢查有無負循環(negative-weight cycle)

  • if d[x] > d[u] + w[u][x] thenreturn false //代表有負循環,無法產生正確結果

  • return d


Bellman ford3

Bellman-Ford最短路徑演算法複雜度

假設G一共有n個節點,m個邊(也就是|V|=n, |E|=m)

  • 行2-5的外層for迴圈一共有n-1次迭代

  • 行3-5的內層for迴圈一共有m次迭代

  • 行4-5為內層if指令,針對每個邊(u, x)依據目前的d[u]值調整d[x]

  • 行6-7的for迴圈在求出(n-1)邊路徑之後再針對每個邊(u, x)依據目前的d[u]值調整d[x],若有任何調整產生則表示有一個n邊路徑(也就是循環)

    因此總時間複雜度為行2-5的外層for迴圈n-1次迭代次數與

    行3-5的內層for迴圈m次迭代相乘得O(n m)= O(|V| |E|)


Bellman ford4

Bellman-Ford最短路徑演算法執行範例


6459115

3.9 Floyd-Warshall最短路徑演算法


Floyd warshall

Floyd-Warshall最短路徑演算法介紹

  • 與Dijkstra演算法與Bellman-Ford演算法不同的是,Floyd-Warshall演算法可以求出全部節點配對的最短路徑,是一個全配對最短路徑(all-pair shortest path)演算法。

  • Floyd-Warshall演算法可以處理有負邊的圖,但是不能用以檢查有負迴圈的圖。


Floyd warshall1

Floyd-Warshall最短路徑演算法介紹(續)

  • Floyd-Warshall演算法採用動態規劃策略解決問題,利用一個n×n(n為節點總數)的二維陣列d來記錄每一節點配對間的最短路徑成本或距離(distance) 。

  • 在啟始(initial)狀況時,d[i][j]=w[i][j],for each i and j。(w[i][j]=0,for i=j; w[i][j]=, for (i, j); w[i][j]=the weight of (i, j) for (i, j) E)

  • Floyd-Warshall演算法執行時會不斷的更新陣列d。在第k次更新陣列d時,表示d中所紀錄的最短路徑是經由編號小於或等於k的節點當作中間節點所造成的。因此,當第n次更新陣列d時,則表示d中所紀錄的最短路徑是可以經由所有節點當作中間節點所造成的,這也就是演算法所需要的結果。


Floyd warshall2

Floyd-Warshall最短路徑演算法

Algorithm Floyd-Warshall最短路徑演算法

Input:G為一個加權圖有向(weighted digraph), G中各邊的加權值以w[x][y]表示,x 及y為邊的二個頂點。

Output:G中的每一個節點配對的最短路徑距離d[x][y],及對應的路徑前節點p[x][y],其中x及y為邊的二個節點

  • d[i][j]=w[i][j],for each i and j

  • for(k←1 to n) do //假設節點的編號由1至n

  • for(i←1 to n) do

  • for(j←1 to n) do

  • if (d[i][j]>d[i][k]+d[k][j])

  • d[i][j]←d[i][k]+d[k][j]

  • p[i][j]←p[k][j]

  • return d


6459115

Floyd-Warshall演算法討論

  • 可以使用一個前節點陣列(predecessor matrix)p紀錄每個節點在最短路徑上的前節點。初始化p[i,j]時,若i=j或(i,j)∉E則初始為NIL(),否則初始為i。

  • 等執行完演算法後,則可藉由前節點陣列來建立出由任意節點到其他任意節點的最短路徑。


Floyd warshall3

Floyd-Warshall最短路徑演算法範例: 陣列初始化

d[i][j]

p[i][j]

G(V, E)


Floyd warshall4

Floyd-Warshall最短路徑演算法複雜度

假設G一共有n個節點(也就是|V|=n)

  • 行2的外層for迴圈一共有n次迭代

  • 行3的中層for迴圈一共有n次迭代

  • 行4的內層for迴圈一共有n次迭代

  • 行5-7的if敘述的執行為常數時間

    因此總時間複雜度為O(n3)=O(|V|3)


6459115

3.10 多階圖最小成本路徑演算法


Multi stage graph minimum cost path problem

多階圖最小成本路徑問題(multi-stage graphminimum-cost path problem)

  • 多階圖G=(V,E) 是有向圖(directed graph),其節點被分割成 k2個互斥集(disjoint sets)Vi, 1i k。

  • 此外,若<u,v>是E的邊,則uVi且vVi+i,1i<k,每個邊都有一個加權(weight)wi,i+1(或稱為成本或距離)。

  • 其中集合 V1和Vk都僅包含一節點(node or vertex)。

  • 多階圖問題是要找出從 V1 中的源點(source)s到 Vk中的標點(target)t 的最小成本路徑(minimum-cost path)。

  • 每一個集合 Vi 被定義為圖中的階(stage)。


6459115

貪婪演算法無法解決多階圖最小成本路徑問題

  • 例:從多階圖(multi-stage graph)中找出v0到v3的最短路徑。

  • 貪婪演算法: v0v1,2v2,1v3 = 23

  • 最佳解: v0v1,1v2,2v3 = 7

  • 貪婪演算法無法解決此問題,這是因為不同階(stage)的決策會影響到其他階的決策。


6459115

貪婪演算法無法解決多階圖最小成本路徑問題(續)

  • 例如:

  • 貪婪演算法無法解決此問題: S A D T 1+4+18 = 23.

  • 最短路徑為:S C F T 5+2+2 = 9.

  • 就像分期買商品一樣,都分三期付款,最終都可以得到商品的產權。有的付款方式第一期要繳1萬,有的要繳2萬,有的要繳5萬。但是依照不同的第一期繳法,則在第二期甚或第三期都有不同的繳款選擇,而造成繳款總額的不同。


6459115

動態規劃

  • 動態規劃方法:

  • d(S, T) = min{1+d(A, T), 2+d(B, T), 5+d(C, T)}


6459115

動態規劃

  • d(A, T) = min{4+d(D, T), 11+d(E, T)}

    = min{4+18, 11+13} = 22.


6459115

動態規劃

  • d(B, T) = min{9+d(D, T), 5+d(E, T), 16+d(F, T)}

    = min{9+18, 5+13, 16+2} = 18.

  • d(C, T) = min{ 2+d(F, T) } = 2+2 = 4

  • d(S, T) = min{1+d(A, T), 2+d(B, T), 5+d(C, T)}

    = min{1+22, 2+18, 5+4} = 9.


6459115

解決多階圖最小成本路徑問題的動態規劃演算法

Algorithm多階圖最小成本路徑演算法

Input:具n個頂點(vertices)的k階多階圖G(V, E), V=ViVj= for ij, V1={1},Vk={n}, <x,y>E (xViyVi+i), <x,y>的權重為w[x,y]

Output: 具k個節點由節點1到節點n的最小成本路徑p[1..k],成本為d[1]

  • d[n]=0; d[1..n-1]=; //陣列d儲存節點到標點t的最小距離(distance)

  • for jk-1 to 1 do

  • for every node x in Vj do

  • for every edge <x, y>E do

  • if (d[x]>w[x,y]+d[y]) do

  • d[x]=w[x,y]+d[y]

  • s[x]=y //s代表節點的下節點(successor)

  • p[1]=1;p[k]=n;

  • for j2 to k-1 do p[j]s[p[j-1]];

  • return p,d[1]


6459115

3.11 最長共同子序列演算法


6459115

最長共同子序列

  • 以下我們說明最長共同子序列(Longest common subsequence, LCS or LCSS)相關背景知識

  • 令X為一個由若干符號依序排列組成的序列(sequence),則X的子序列(subsequence)為從X刪除0個或多個符號(不必要為連續性的)的序列

  • 例:令X= b a c a d,則ad, ac, bac, acad, bacad, bcd等與空序列都是A的子序列

  • 例: 序列X = b a c a d 與Y = a c c b a d c b 的共同子序列(common subsequence)有: ad, ac, bac, acad等

  • 例: 序列X與Y的最長共同子序列(longest common subsequence)為:a c a d


6459115

最長共同子序列應用:DNA序列比對

DNA = {A|C|G|T}*

(A: 腺嘌呤;C: 胞嘧啶; G: 鳥嘌呤; T: 胸腺嘧啶)

S1=ACCGGTCGAGTGCGGCCGAAGCCGGCCGAA

S2=GTCGTTCGGAATGCCGTTGCTGTAAA

Q:S1與S2是否為相似的DNA序列?

A: 這問題可以由找出S1與S2的最長共同子序列來解決。


6459115

最長共同子序列應用:化身路徑群組

化身路徑群組(Avatar Path Clustering):

  • 由於相似的個性,興趣或習慣,網路虛擬環境(Networked Virtual Environment, NVE)或巨量多人線上遊戲(Massively Multiplayer Online Game, MMOG)的用戶或化身(avatar)可能具有相似的行為模式,導致在虛擬世界中有著類似的化身路徑。

  • 我們希望將類似的化身歸類為一個群組,並為他們找到代表性路徑(representative path, RP)。

  • 參考論文: Jehn-RueyJiang, Ching-Chuan Huang, and Chung-Hsien Tsai, “Avatar Path Clustering in Networked Virtual Environments," in Proc. of the 4th International Workshop on Peer-to-Peer Networked Virtual Environments (P2PNVE 2010), 2010.

  • 下圖來源: HuiguangLiang, RansiNilakshaSilva, Wei Tsang Ooi, MehulMotani, “Avatar mobility in user-created networked virtual worlds: measurements, analysis, and implications,” Multimedia Tools and Applications, v.45 n.1-3, p.163-190, October 2009.


6459115

最長共同子序列應用:化身路徑群組(續)

  • 在第二人生(Second Life, SL)贈品島(Freebies Island)的兩條路徑有多相似?


6459115

最長共同子序列應用:化身路徑群組(續)

將化身路徑轉為序列:

將虛擬世界切割為方格(grid cell),並針對化身路徑每隔固定時間取樣,找出其所在方格編號形成序列。

SeqA:C60.C61.C62.C63.C55.C47.C39.C31.C32


6459115

最長共同子序列應用:化身路徑群組(續)

SeqA:C60.C61.C62.C63.C55.C47.C39.C31.C32

SeqB:C60.C61.C62.C54.C62.C63.C64

LCSSAB :C60.C61.C62. C63

找出兩條路徑對應的最長共同子序列以衡量其相似程度。


6459115

最長共同子序列問題

以下我們定義最長共同子序列(Longest Common Subsequence, LCS)問題:

  • 給定兩個序列X = <x1,x2,...,xm>, Y = <y1,y2,...,yn>,找出X和Y的最長共同子序列長度


6459115

最長共同子序列問題暴力法時間複雜度

產生序列X(或Y)的所有子序列,然後檢查每個子序列是否也是序列Y(或X)的子序列,然後儲存下最長的子序列並輸出。複雜度為:

  • n * 2m = O(2m)

  • m * 2n = O(2n )

    Q1:如何產生一個序列的所有子序列?

    Q2:如何檢查一個序列是否為另一個序列的子序列?


6459115

最長共同子序列問題子問題的遞迴關係

我們定義Xi = < x1,x2,...,xi >及Yj= <y1,y2,...,yj>。令c [i, j]是Xi 和Yj的LCS的長度,則我們有以下遞迴關係:

ì

0

if

i=

0

or

j=

0

ï

=

-

-

+

c

[

i

,

j

]

c

[

i

1

,

j

1

]

1

if

i,j>

0

and

x

=y

í

i

j

ï

-

-

¹

max{

c

[

i

,

j

1

],

c

[

i

1

,

j

]}

if

i,j>

0

and

x

y

î

i

j


6459115

最長共同子序列演算法

Algorithm 最長共同子序列演算法

Input: 兩個序列X= <x1,x2,...,xm>, Y = <y1,y2,...,yn>

Input: X和Y的最長共同子序列長度

1m length[X]

2 n length[Y]

3 fori1tom do

4 c[i, 0]  0

5 forj 1ton do

6 c[0, j]  0


6459115

7 fori 1 tom do

8 forj 1ton do

9 ifxi = yjthen

10 c[i, j]  c[i-1, j-1]+1

11 b[i, j] 0 “” //for both i-1 and j-1

12 else if c[i–1, j] c[i, j-1] then

13 c[i, j]  c[i-1, j]

14 b[i, j]  “” //for i-1

15 elsec[i, j] c[i, j-1]

16b[i, j]  “” //for j-1 only

17 returnc and b


6459115

最長共同子序列演算法

執行範例

X=ABCBDAB

Y=BDCABA


6459115

最長共同子序列演算法

時間複雜度

  • 行7的外層for迴圈一共有m次迭代

  • 行8的內層for迴圈一共有n次迭代

  • 行9-16的if敘述需要常數時間

  • 因此總時間複雜度為O(mn) ,而非暴力法的 O(2m)或 O(2n)


6459115

最長共同子序列演算法如何找出最長共同子序列

PRINT_LCS(b, X, i, j )

1ifi = 0orj = 0then

2return

3ifb[i, j] = “” then

4PRINT_LCS(b, X, i-1, j-1)

5print xi

6else ifb[i, j] = “” then

7PRINT_LCS(b, X, i-1, j)

8else PRINT_LCS(b, X, i, j-1)

時間複雜度: O(m+n)

藉由呼叫PRINT_LCS(b, X, length[X], length[Y])函數來印出LCS


6459115

3.12 矩陣鏈乘積演算法


Matrix chain product

矩陣鏈乘積(matrix-chain product)

  • Q: 如何以最少的純量(scalar)乘法,算出A1…An的矩陣鏈乘積?

  • A: 加上括號指定計算矩陣乘積最佳順序

  • 舉例:


6459115

二個矩陣相乘的演算法

MATRIX MULTIPLY(A,B)

1if columns[A] rows[B]

2 then error“不相容的矩陣大小”

3 else for to rows[A]

4 forto columns[B]

5

6 forto columns[A]

7

8returnC


6459115

二個矩陣相乘時間複雜度:

  • 假設A是一個的矩陣,B是一個

    的矩陣,那個A xB 的時間複雜度為。


6459115

矩陣相乘執行順序非常關鍵

  • 假設是個的矩陣, 是一個的矩陣, 是一個的矩陣。

  • 那麼算出 需要

    次的純量相乘。

  • 然而算出 卻需要

    次的純量相乘。


Matrix chain product problem

矩陣鏈乘積問題(matrix-chain productproblem)

  • 給定一長度為n的矩陣鏈,對於i=1,2,…,n而言,矩陣Ai 的維度為pi-1pi。找出一種方式對 進行完全括號(fully parenthesized)以最少的純量乘法求出矩陣鏈乘積。

  • 若一個矩陣鏈乘積為完全括號,則其包含單一矩陣或為兩個完全括號矩陣鏈乘積的相乘。


6459115

矩陣鏈乘積問題窮舉所有不同的括號方式:

  • 不同括號方式總數相當於將矩陣鏈在第k個矩陣之後與第k+1個矩陣之前,使用括號分為二組後再計算其結果,而1kn-1。我們可得:

  • 實際上,P(n)為卡塔蘭數(Catalan number)=Cn-1 =O(2n)


Catalan number

卡塔蘭數(Catalan number)

  • 卡塔蘭數是以比利時的數學家歐仁查理卡塔蘭(EugèneCharles Catalan, 1814–1894)命名。

  • 卡塔蘭數的一般項公式為 


6459115

矩陣鏈乘積演算法解題思維步驟1:找出子問題切割方式


6459115

矩陣鏈乘積演算法解題思維步驟2: 找出子問題遞迴關係

  • 定義 m[i, j]= 計算 所需的最小相乘數。

  • 目標為求得 m[1, n]


6459115

矩陣鏈乘積演算法解題思維步驟3: 以表格儲存計算過的資訊

  • 與其一再地遇到相同問題而重複遞迴求解,取而代之地我們利用一表格化的(tabular)、由下而上(bottom-up)的方式來計算最低成本。

  • 過程利用一輔助表格m[1..n, 1..n] 來紀錄最小成本m[i, j] ,並利用另一個輔助表格s[1..n, 1..n]來記錄哪一個指標 k 造就了m[i, j]的最小成本。


Matrix chain order

矩陣鏈乘積演算法MATRIX_CHAIN_ORDER

MATRIX_CHAIN_ORDER(p)

1 n length[p] –1

2 fori 1 ton

3dom[i,i]  0

4 forl 2ton

5do fori 1ton – l + 1

6doj i + l – 1

7 m[i, j]  

8 fork itoj – 1

9doq m[i, k] + m[k+1, j]+ pi-1pkpj

10 ifq < m[i, j]

11 thenm[i, j]  q

12 s[i, j]  k

13 returnm and s

時間複雜度:


6459115

例子:


6459115

在n=6時,MATRIX-CHAIN-ORDER所計算出的

m 與 s 表格


6459115

m[2,5]=

min{

m[2,2]+m[3,5]+p1p2p5=0+2500+351520=13000,

m[2,3]+m[4,5]+p1p3p5=2625+1000+35520=7125,

m[2,4]+m[5,5]+p1p4p5=4375+0+351020=11374

}

=7125


6459115

印出最佳括號方式

PRINT_OPTIMAL_PARENS(s, i, j)

1 ifi=j

2 then print “A”i

3 else print “(“

4 PRINT_OPTIMAL_PARENS(s, i, s[i,j])

5 PRINT_OPTIMAL_PARENS(s, s[i,j]+1, j)

6 print “)”

  • 例:


6459115

The End


  • Login