Upload
bailey-mckay
View
216
Download
0
Embed Size (px)
Citation preview
演算法期末報告
第三組96703046 譚岳民98207429 葉玫慈99703002 劉奕廷
[UVa]291 - The House Of Santa Claus
[UVa]291 - The House Of Santa Claus
• In your childhood you most likely had to solve the riddle of the house of Santa Claus. Do you remember that the importance was on drawing the house in a stretch without lifting the pencil and not drawing a line twice? As a reminder it has to look like shown in Figure 1.
[UVa]291 - The House Of Santa Claus
• Well, a couple of years later, like now, you have to ``draw'' the house again but on the computer. As one possibility is not enough, we require all the possibilities when starting in the lower left corner. Follow the example in Figure 2 while defining your stretch.
Figure: This Sequence would give the Output line 153125432
[UVa]291 - The House Of Santa Claus
• All the possibilities have to be listed in the output file by increasing order, meaning that 1234... is listed before 1235... .
• Output So, an output file could look like this: 12435123 13245123 ... 15123421
尤拉路徑 (Euler Path)(一筆劃問題 )
• 尤拉路徑可分為尤拉迴路 (Euler Cycle)和尤拉鏈 (Euler
Chain)
其差異就是「奇點」的數量。
• 尤拉路徑的定理是在圖形中,必須要有「零個」或是「兩個」奇點
• 而所謂的奇點就是「與它連接的路徑只有奇數個」
• Cycle就是奇點 0個的情況, Chain則是奇點 2個的情況。
Depth-First Search
• 深度優先 (depth first) 的搜尋 : 在尋找解的過程中,若有某分支能展開則優先展開該分支,其餘分支等該分支返回後才繼續展開
• DFS on a graph with n vertices and m edges takes O(n + m ) time
• Depth-first search is to graphs what Euler tour is to binary trees
Depth-First Search 7
DFS Algorithm
• The algorithm uses a mechanism for setting and getting “labels” of vertices and edges
Algorithm DFS(G, v)Input graph G and a start
vertex v of G Output labeling of the edges of
G in the connected
component of v as discovery edges
and back edgessetLabel(v, VISITED)
for all e G.incidentEdges(v)if getLabel(e) =
UNEXPLOREDw opposite(v,e)if getLabel(w) =
UNEXPLORED
setLabel(e, DISCOVERY)DFS(G,
w)else
setLabel(e, BACK)
Algorithm DFS(G)Input graph GOutput labeling of the
edges of G as discovery edges
andback edges
for all u G.vertices()setLabel(u,
UNEXPLORED)for all e G.edges()
setLabel(e, UNEXPLORED)for all v G.vertices()
if getLabel(v) = UNEXPLORED
DFS(G, v)
Example
Depth-First Search 8
DB
A
C
E
DB
A
C
E
DB
A
C
E
discovery edgeback edge
A visited vertexA unexplored vertex
unexplored edge
Example (cont.)
Depth-First Search 9
DB
A
C
E
DB
A
C
E
DB
A
C
E
DB
A
C
E
Depth-First Search 10
Properties of DFS
Property 1DFS(G, v) visits all the vertices and edges in the connected component of v
Property 2The discovery edges labeled by DFS(G, v) form a spanning tree of the connected component of v
DB
A
C
E
Depth-First Search 11
Analysis of DFS
• Setting/getting a vertex/edge label takes O(1) time• Each vertex is labeled twice
– once as UNEXPLORED– once as VISITED
• Each edge is labeled twice– once as UNEXPLORED– once as DISCOVERY or BACK
• Method incidentEdges is called once for each vertex• DFS runs in O(n + m) time provided the graph is
represented by the adjacency list structure– Recall that Sv deg(v) = 2m
解題策略• 使用 DFS來實作• 規定是要從 1為起點,由觀察可知 2為其終點。• 真正的「完成」條件:把所有的路徑走過一次。• 可用 adjacency matrix 或 adjacency list 紀錄此路可否通與是否有走過這段路,然後再進入遞迴之中尋求路徑
• 以 125315432這組測資來說:
#include <stdio.h>#include <stdlib.h>int map[5][5] = {{0,1,1,0,1},{1,0,1,0,1},{1,1,0,1,1},{0,0,1,0,1},
{1,1,1,1,0}};int ans[8] = {0};void DFS(int idx, int now) { ans[idx] = now; if(idx == 8) { for(int i = 0; i < 9; i++){ printf("%d", ans[i]+1);} puts(""); return ; } int i=0;
adjacency matrix 解法
for(i = 0; i < 5; i++) { if(map[now][i] == 1) { map[now][i] = map[i][now] = 0; DFS(idx+1, i); map[now][i] = map[i][now] = 1; } }} int main() { DFS(0, 0); return 0;}
adjacency matrix 解法 續
時間複雜度分析
• 因為這個程式的架構就是 DFS。用 adjacency matrix實作時間複雜度是 N^2。 故 O(v^2) 因為原本的演算法只要走過的點,就不會再走一次。
• 首先是程式的 recursive總數為 240次再來算出程式的總 step數,約 6000上下。6000/240→25(5^2)。
#include <stdio.h>#include <stdlib.h>#define MAXEDGE 8#define MAXNODE 6 /* Node 0~5 */typedef struct node { /* pos: edge position */ int pos, node; struct node *next;} Node;typedef enum {FALSE = 0, TRUE} bool;void init(int, int, int); void backtrack(int, int); void freeg(void);Node *g[MAXNODE] = {NULL};bool visited[MAXEDGE]; char output[MAXEDGE + 1];
adjacency list 解法
bool visited[MAXEDGE]; char output[MAXEDGE + 1];int main(void){ int i; init(1, 2, 0); init(2, 1, 0); init(1, 3, 1); init(3, 1, 1); init(1,
5, 2); init(5, 1, 2); init(2, 3, 3); init(3, 2, 3); init(2, 5, 4); init(5, 2, 4); init(3,
4, 5); init(4, 3, 5); init(3, 4, 5); init(4, 3, 5); init(3, 5, 6); init(5, 3, 6); init(4,
5, 7); init(5, 4, 7); output[0] = 1 + '0'; backtrack(1, 1); freeg(); return 0;}
adjacency list 解法 續
void init(int v1, int v2, int pos){ Node *pt, *tmp; tmp = (Node *)malloc(sizeof(Node)); tmp->next = NULL; tmp->node = v2; tmp->pos = pos; if (g[v1] == NULL) { g[v1] = tmp; return; } pt = g[v1]; while (pt->next != NULL) pt = pt->next; pt->next = tmp;}
/* backtrack: use backtracking method to output answer */void backtrack(int index, int node){ Node *pt; int pos;
if (index == MAXEDGE + 1) { output[index] = '\0'; printf("%s\n", output); return; }
for (pt = g[node]; pt; pt = pt->next) { pos = pt->pos; node = pt->node; if (!visited[pos]) { visited[pos] = TRUE; output[index] = node + '0'; backtrack(index + 1, node); visited[pos] = FALSE; } }}
/* freeg: free all graph node */void freeg(void){ Node *pt, *tmp; int i;
for (i = 0; i < MAXNODE; i++) { pt = g[i]; while (pt != NULL) { tmp = pt; pt = pt->next; free(tmp); } }}
adjacency list 解法 續
/* backtrack: use backtracking method to output answer */void backtrack(int index, int node){ Node *pt; int pos; if (index == MAXEDGE + 1) { output[index] = '\0‘; printf("%s\n", output); return; } for (pt = g[node]; pt; pt = pt->next) { pos = pt->pos; node = pt->node; if (!visited[pos]) { visited[pos] = TRUE; output[index] = node + '0'; backtrack(index + 1, node); visited[pos] = FALSE; } } }
/* freeg: free all graph node */void freeg(void){ Node *pt, *tmp; int i;
for (i = 0; i < MAXNODE; i++) { pt = g[i]; while (pt != NULL) { tmp = pt; pt = pt->next; free(tmp); } }}
adjacency list 解法 續
/* freeg: free all graph node */void freeg(void){ Node *pt, *tmp; int i; for (i = 0; i < MAXNODE; i++) { pt = g[i]; while (pt != NULL) { tmp = pt; pt = pt->next; free(tmp); } }}
adjacency list 解法 續
時間複雜度分析
• 因為 adjacency list的演算法會因頂點數和邊數的不同而影響時間。
• 而這個演算法是掃邊之後接下來要跑的頂點數就會變少
• 所以是用 adjacency list實作時間複雜度是 O(E*logV)
• 首先是程式的 recursive總數為 195次再來算出程式的總 step數,約 1200上下。1200/195→6.1538…..。
#include <stdio.h>
int main(void){printf("123153452\n123154352\n123451352\n123453152\n123513452\n123543152\n125134532\n125135432\n125315432\n125345132\n125431532\n125435132\n132153452\n132154352\n132534512\n132543512\n134512352\n134512532\n134521532\n134523512\n134532152\n134532512\n135123452\n135125432\n135215432\n135234512\n135432152\n135432512\n152134532\n152135432\n152345312\n152354312\n153123452\n153125432\n153213452\n153254312\n153452132\n153452312\n154312352\n154312532\n154321352\n154325312\n154352132\n154352312\n");return 0;}
前處理法
時間複雜度分析
• 前處理法只有一個 printf , 所以時間複雜度為 O(1)
運行結果
運行結果
共 44種
演算法 時間複雜度
優點 缺點
相鄰矩陣 O(V*V) 直觀 ,好除錯
費時
相鄰 list O(E*logV) 省時 比較不好除錯
前處理法 O(1) 簡單 要先有答案才能解