45
101 北 一女 北北北北北北北 深深深深深深 (DFS) 深 深深深深深深 (BFS) 2012.07.08 Nan

101 北一女中 資訊選手培訓營

  • Upload
    davida

  • View
    58

  • Download
    0

Embed Size (px)

DESCRIPTION

101 北一女中 資訊選手培訓營. 深度優先搜尋 (DFS) 與 廣度優先搜尋 (BFS). 2012.07.08 Nan. 學了圖論基礎後 ….what’s next?. 走訪 - Traversal. 給你一張圖,把所有的節點走過一次的方法,我們稱為圖的走訪 (Graph Traversal) 走訪可以有任意順序,但是特定的順序會產生特定的性質。 最常用的走訪有兩種: 深度優先搜尋 (Depth First Search, DFS) 廣度優先搜尋 (Breath First Search, BFS). 1. 3. 5. 2. 6. 4. - PowerPoint PPT Presentation

Citation preview

Page 1: 101 北一女中 資訊選手培訓營

101 北一女中資訊選手培訓營深度優先搜尋 (DFS)

與廣度優先搜尋 (BFS)2012.07.08 Nan

Page 2: 101 北一女中 資訊選手培訓營

學了圖論基礎後… .what’s next?

Page 3: 101 北一女中 資訊選手培訓營

走訪 - Traversal

• 給你一張圖,把所有的節點走過一次的方法,我們稱為圖的走訪 (Graph Traversal)

• 走訪可以有任意順序,但是特定的順序會產生特定的性質。

• 最常用的走訪有兩種:深度優先搜尋 (Depth First Search, DFS)廣度優先搜尋 (Breath First Search, BFS)

Page 4: 101 北一女中 資訊選手培訓營

舉個例子來說

11 33

22

44

66

55

Page 5: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

1

堆疊 Stack

Page 6: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

1

2

Page 7: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

1

2

4

Page 8: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

1

2

Page 9: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

1

2

6D = 2

Page 10: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

1

2

6D = 2

D = 3

3

Page 11: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

1

2

6D = 2

D = 3

Page 12: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

1

2

6D = 2

D = 3

D = 3

5

Page 13: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

1

2

6D = 2

D = 3

D = 3

Page 14: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

1

2

D = 2

D = 3

D = 3

Page 15: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

1

D = 2

D = 3

D = 3

Page 16: 101 北一女中 資訊選手培訓營

深度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2 D = 2

D = 3

D = 3

走訪順序: 1 2 4 6 3 5

Page 17: 101 北一女中 資訊選手培訓營

實作• 通常都用遞迴來實作• 你剛剛看到的堆疊會因此隱藏起來 ( 遞迴會

有系統的堆疊 )• 習慣上會把 map 、 visited( 紀錄有沒有被

走過的、以及其他相關資訊放到 global 變數,讓遞迴能夠存取。

Page 18: 101 北一女中 資訊選手培訓營

int N = # node;int map[N+1][N+1] = {{…},{…},…};int visited[N+1] = {0};int depth[N+1];

void dfs(int id){ int i; printf(“%d\n”, id); for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i); } } }

int main(){ visited[1] = 1; depth[1] = 0; dfs(1);}

Page 19: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

1

堆疊

visited[1] = 1; depth[1] = 0; dfs(1);

void dfs(int id){ int i; for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i);

dfs(2)

Page 20: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

D = 1

1

2

dfs(2)

void dfs(int id){ int i; for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i);

dfs(4)

Page 21: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

D = 1

D = 2

1

2

4

dfs(4)

void dfs(int id){ int i; for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i);

結束 !return! 會回到 dfs(2) 時的 for 迴圈繼續跑

Page 22: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

D = 1

D = 2

1

2

return 回到dfs(4)

void dfs(int id){ int i; for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i);

dfs(6)

Page 23: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

D = 1

D = 2

1

2

6D = 2

dfs(6)

void dfs(int id){ int i; for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i);

dfs(3)

Page 24: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

D = 1

D = 2

1

2

6D = 2

D = 3

3

dfs(3)

void dfs(int id){ int i; for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i);

結束 !return! 會回到 dfs(6) 時的 for 迴圈繼續跑

Page 25: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

D = 1

D = 2

1

2

6D = 2

D = 3

return 回到dfs(6)

void dfs(int id){ int i; for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i);

dfs(5)

Page 26: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

D = 1

D = 2

1

2

6D = 2

D = 3

D = 3

5

dfs(5)

void dfs(int id){ int i; for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i);

結束 !return! 會回到 dfs(6) 時的 for 迴圈繼續跑

Page 27: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

D = 1

D = 2

1

2

6D = 2

D = 3

D = 3

return 回到dfs(6)

void dfs(int id){ int i; for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i);

結束 !return! 會回到 dfs(2) 時的 for 迴圈繼續跑

Page 28: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

D = 1

D = 2

1

2

D = 2

D = 3

D = 3

return 回到dfs(2)

void dfs(int id){ int i; for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i);

結束 !return! 會回到 dfs(1) 時的 for 迴圈繼續跑

Page 29: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

D = 1

D = 2

1

D = 2

D = 3

D = 3

return 回到dfs(1)

void dfs(int id){ int i; for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; depth[i] = depth[id] + 1; dfs(i);

結束 !return! 會回到 main 去 結束 !

Page 30: 101 北一女中 資訊選手培訓營

11 33

22

44

66

55

D = 0

D = 1

D = 2 D = 2

D = 3

D = 3

print 出來的: 1 2 4 6 3 5

return 回到main 裡的 dfs(1) 後,等於完成 ~

Page 31: 101 北一女中 資訊選手培訓營

你可能有聽過所謂的“暴搜”• DFS 的變化型,本來是只找一種走法把圖

走過,變成試過所有走法• 關鍵點在於 : 自己的鄰居都走完 return 回

來後,把自己設回沒有走過。• 或者反過來說是每個鄰居下去走過以後,

設回沒走過• 通常需要一個暫存的陣列放置目前走訪的

順序,走到底再一次印出

Page 32: 101 北一女中 資訊選手培訓營

int N = # node;int map[N+1][N+1] = {{…},{…},…};int visited[N+1] = {0};int path[N+1];

void dfs(int id, int depth){ int i; if ( depth >= N ){ for ( i = 0 ; i < N ; i++ ) printf(“ %d”, path[i]); putchar(‘\n’); return; } for ( i = 1 ; i <= N ; i++ ){ if ( map[id][i] == 1 && visited[i] == 0 ) { visited[i] = 1; path[depth] = i; dfs(i, depth + 1); visited[i] = 0; // 還原 ! } } }

int main(){ visited[1] = 1; path[0] = 1; dfs(1, 1);}

Page 33: 101 北一女中 資訊選手培訓營

廣度優先搜尋

11 33

22

44

66

55

D: 深度

1

D = 0

佇列 (Queue)

Page 34: 101 北一女中 資訊選手培訓營

廣度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

1 2 3

D = 1

D = 1

Page 35: 101 北一女中 資訊選手培訓營

廣度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

2 3

D = 1

D = 1

咖啡色:已經走過橘色:目前所在位置皮膚色:已在 queue 中粉紅色:此次加入 queue

4 6

D = 2D = 2

Page 36: 101 北一女中 資訊選手培訓營

廣度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

3

D = 1

D = 2

咖啡色:已經走過橘色:目前所在位置皮膚色:已在 queue 中粉紅色:此次加入 queue

4 6

D = 2D = 2

Page 37: 101 北一女中 資訊選手培訓營

廣度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

咖啡色:已經走過橘色:目前所在位置皮膚色:已在 queue 中粉紅色:此次加入 queue

4 6

D = 2D = 2

Page 38: 101 北一女中 資訊選手培訓營

廣度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

咖啡色:已經走過橘色:目前所在位置皮膚色:已在 queue 中粉紅色:此次加入 queue

6

D = 2D = 2

5

D = 3

Page 39: 101 北一女中 資訊選手培訓營

廣度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

咖啡色:已經走過橘色:目前所在位置皮膚色:已在 queue 中粉紅色:此次加入 queue

D = 2D = 2

5

D = 3

Page 40: 101 北一女中 資訊選手培訓營

廣度優先搜尋

11 33

22

44

66

55

D = 0

D: 深度

D = 1

D = 2

D = 2D = 2

D = 3

走訪順序: 1 2 3 4 6 5

Page 41: 101 北一女中 資訊選手培訓營

實做 ( 通常直接在 main 裡 )int N = # nodes;int q[N * N + 1];int map[N+1][N+1] = {{…},{…},…};int visited[N+1] = {0};int head, tail = 0;int i;q[0] = 1;visited[1] = 1;

for(head=0; head<tail; head++){

for(i=1; i<=N; i++){

if(visited[i] == 0 && map[q[head]][i] == 1) {

q[tail] = i; tail++;

}}

}

Page 42: 101 北一女中 資訊選手培訓營

實做 ( 棋盤式地圖 )int way_x[4] = {1, -1, 1, -1};int way_y[4] = {1, 1, -1, -1};for(head=0; head<tail; head++){

for(i=0; i<4; i++) { if(map[qx[head] + way_x[i]][qy[head] + way_y[i]]) {

map[qx[head] + way_x[i]][qy[head] + way_y[i]] = 1;

qx[tail] = qx[head] + way_x[i];qy[tail] = qy[head] + way_y[i];qn[tail] = qn[head] + 1;tail++;

} }

}

Page 43: 101 北一女中 資訊選手培訓營

BFS 的特性• 將同一層的所有節點走完,才會走向下一層• 走出來的會是最短路徑 ( 假設邊的 weight = 1)• 用 Queue 來輔助• 時間複雜度 O(V + E)

Page 44: 101 北一女中 資訊選手培訓營

DFS vs. BFS

11 33

22

44

66

55

11 33

22

44

66

55

Page 45: 101 北一女中 資訊選手培訓營

DFS vs. BFS

11

3322

44 66

55

11

33

22

44 66

55