UVa 291

UVa 291

題目

http://domen111.github.io/UVa-Easy-Viewer/?291

如下圖所示,有編號 $1$~$5$ 的五個點,假設每一條邊都是雙向的

列出所有從 $1$ 開始每條邊最多只經過一次,並且每個點都有走到的情況,也就是一筆劃問題

想法

要枚舉有哪些情況,就必須要先知道每個點可以連接到哪些點

我們可以預處理一張表,紀錄 $a$ 到 $b$ 是否有邊連通

接下來要符合一條邊的情況,就必須記錄每條邊是否被走過

一樣的,可以用一個表格紀錄 $a$ 到 $b$ 之間的邊是否被走過

最後就從 $1$ 點開始對於每個可以走的點都走過一次,枚舉出所有情況即可

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//By Koios1143
#include<iostream>
using namespace std;
bool nxt[6][6];
int res[10], vis[6][6];

void DFS(int depth, int last){
if(depth == 9){
for(int i=0 ; i<9 ; i++){
cout<<res[i];
}
cout<<"\n";
return;
}
for(int i=1 ; i<=6 ; i++){
// 確認 last 到 i 之間的邊是否走過
if(!vis[last][i] && !vis[i][last] && nxt[last][i]){
vis[last][i] = vis[i][last] = true;
res[depth] = i;
DFS(depth+1, i);
vis[last][i] = vis[i][last] = false;
}
}
}

int main(){
for(int i=0 ; i<6 ; i++){
for(int j=0 ; j<6 ; j++){
if(i==0) nxt[i][j] = true;
else nxt[i][j] = false;
vis[i][j] = false;
}
}
// 建立兩個點之間是否有邊的表
nxt[1][2] = nxt[1][3] = nxt[1][5] = true;
nxt[2][1] = nxt[2][3] = nxt[2][5] = true;
nxt[3][1] = nxt[3][2] = nxt[3][4] = nxt[3][5] = true;
nxt[4][3] = nxt[4][5] = true;
nxt[5][1] = nxt[5][2] = nxt[5][3] = nxt[5][4] = true;
res[0]=1;
DFS(1, 1);
return 0;
}

時間複雜度分析

DFS 每層最多 $4$ 種選擇,總共有 $8$ 層,時間複雜度為 $O(4^8)$