96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

27
演演演 演演演演 演演演 96703046 演演演 98207429 演演演 99703002 演演演 [UVa]291 - The House Of Santa Claus

Transcript of 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

Page 1: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

演算法期末報告

第三組96703046 譚岳民98207429 葉玫慈99703002 劉奕廷

[UVa]291 - The House Of Santa Claus

Page 2: 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.

Page 3: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

[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

Page 4: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

[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

Page 5: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

尤拉路徑 (Euler Path)(一筆劃問題 )

• 尤拉路徑可分為尤拉迴路 (Euler Cycle)和尤拉鏈 (Euler

Chain)

其差異就是「奇點」的數量。    

• 尤拉路徑的定理是在圖形中,必須要有「零個」或是「兩個」奇點    

• 而所謂的奇點就是「與它連接的路徑只有奇數個」    

• Cycle就是奇點 0個的情況, Chain則是奇點 2個的情況。

Page 6: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

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

Page 7: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

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)

Page 8: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

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

Page 9: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

Example (cont.)

Depth-First Search 9

DB

A

C

E

DB

A

C

E

DB

A

C

E

DB

A

C

E

Page 10: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

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

Page 11: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

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

Page 12: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

解題策略• 使用 DFS來實作• 規定是要從 1為起點,由觀察可知 2為其終點。• 真正的「完成」條件:把所有的路徑走過一次。• 可用 adjacency matrix 或  adjacency list 紀錄此路可否通與是否有走過這段路,然後再進入遞迴之中尋求路徑

• 以 125315432這組測資來說:

Page 13: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

#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 解法

Page 14: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

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 解法 續

Page 15: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

時間複雜度分析

• 因為這個程式的架構就是  DFS。用 adjacency matrix實作時間複雜度是 N^2。 故 O(v^2) 因為原本的演算法只要走過的點,就不會再走一次。

• 首先是程式的 recursive總數為 240次再來算出程式的總 step數,約 6000上下。6000/240→25(5^2)。

Page 16: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

#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 解法

Page 17: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

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 解法 續

Page 18: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

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 解法 續

Page 19: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

/* 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 解法 續

Page 20: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

/* 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 解法 續

Page 21: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

時間複雜度分析

• 因為 adjacency list的演算法會因頂點數和邊數的不同而影響時間。

• 而這個演算法是掃邊之後接下來要跑的頂點數就會變少

• 所以是用 adjacency list實作時間複雜度是 O(E*logV)

• 首先是程式的 recursive總數為 195次再來算出程式的總 step數,約 1200上下。1200/195→6.1538…..。

Page 22: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

#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;}

前處理法

Page 23: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

時間複雜度分析

• 前處理法只有一個 printf , 所以時間複雜度為 O(1)

Page 24: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

運行結果

Page 25: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

運行結果

Page 26: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

共 44種

Page 27: 96703046 98207429 99703002 [UVa]291 - The House Of Santa Claus.

演算法 時間複雜度

優點 缺點

相鄰矩陣 O(V*V) 直觀 ,好除錯

費時

相鄰 list O(E*logV) 省時 比較不好除錯

前處理法 O(1) 簡單 要先有答案才能解