UVa 216
http://domen111.github.io/UVa-Easy-Viewer/?216
在平面座標上有 $n$ 個點,我們要用 $n-1$ 條網路線連接這 $n$ 個點
為了安裝方便,兩台電腦之間會多預留 $16$ 呎的網路線
是否能找到一種連接方式,使得電腦都有網路線連接,並且網路線總長度最少
$2 \leq n \leq 8$
想法
這一題的 $n$ 很小,所以我們可以考慮比較暴力的作法
任意選擇一個起點,然後往下任意選擇下一個點,一直做到每個點都選擇到了,然後計算長度,把當前最短的長度所經過的點都記錄下來
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 44 45 46 47 48 49 50 51 52 53 54 55 56
| #include<iostream> #include<iomanip> #include<cmath> using namespace std; int n, Case=1, x[10], y[10], tmpx[10], tmpy[10], rx[10], ry[10]; bool used[10]; double tot, min_dis;
double dist(int p, int q, int m, int n){ return sqrt(pow(p-m, 2) + pow(q-n, 2)); }
void dfs(int depth, double path){ if(depth == n){ if(path < min_dis){ min_dis = path; for(int i=0 ; i<n ; i++){ rx[i] = tmpx[i]; ry[i] = tmpy[i]; } } return; } for(int i=0 ; i<n ; i++){ if(!used[i]){ used[i] = true; tmpx[depth] = x[i]; tmpy[depth] = y[i]; if(depth == 0) dfs(depth+1, 0); else dfs(depth+1, path+dist(tmpx[depth], tmpy[depth], tmpx[depth-1], tmpy[depth-1])+16); used[i] = false; } } }
int main(){ while(cin>>n && n){ min_dis=2147483647; for(int i=0 ; i<n ; i++){ cin>>x[i]>>y[i]; used[i] = false; } dfs(0, 0); cout<<"**********************************************************\n"; cout<<"Network #"<<Case++<<"\n"; for(int i=1 ; i<n ; i++){ cout<<"Cable requirement to connect ("<<rx[i-1]<<","<<ry[i-1]<<") to ("<<rx[i]<<","<<ry[i]<<") is "<<fixed<<setprecision(2)<<dist(rx[i-1], ry[i-1], rx[i], ry[i])+16<<" feet.\n"; } cout<<"Number of feet of cable required is "<<min_dis<<".\n"; } return 0; }
|
時間複雜度分析
每筆測資輸入時間複雜度為 $O(n)$
DFS 每一層最多有 $n$ 種選擇,總共有 $n$ 層,並且最後一層需要 $O(n)$ 的時間複製當前答案
每筆測資 DFS 時間複雜度為 $O(n^n \times n) = O(n^{n+1})$
每筆測資總時間複雜度約為 $O(n^{n+2})$