問題描述 2015年,全中國實現了戶戶通電。做爲一名電力建設者,小明正在幫助一帶一路上的國家通電。 這一次,小明要幫助 n 個村莊通電,其中 1 號村莊正好能夠創建一個發電站,所發的電足夠全部村莊使用。 如今,這 n 個村莊之間都沒有電線相連,小明主要要作的是架設電線鏈接這些村莊,使得全部村莊都直接或間接的與發電站相通。 小明測量了全部村莊的位置(座標)和高度,若是要鏈接兩個村莊,小明須要花費兩個村莊之間的座標距離加上高度差的平方,形式化描述爲座標爲 (x_1, y_1) 高度爲 h_1 的村莊與座標爲 (x_2, y_2) 高度爲 h_2 的村莊之間鏈接的費用爲 sqrt((x_1-x_2)*(x_1-x_2)+(y_1-y_2)*(y_1-y_2))+(h_1-h_2)*(h_1-h_2)。 在上式中 sqrt 表示取括號內的平方根。請注意括號的位置,高度的計算方式與橫縱座標的計算方式不一樣。 因爲經費有限,請幫助小明計算他至少要花費多少費用才能使這 n 個村莊都通電。 輸入格式 輸入的第一行包含一個整數 n ,表示村莊的數量。 接下來 n 行,每一個三個整數 x, y, h,分別表示一個村莊的橫、縱座標和高度,其中第一個村莊能夠創建發電站。 輸出格式 輸出一行,包含一個實數,四捨五入保留 2 位小數,表示答案。 樣例輸入 4 1 1 3 9 9 7 8 8 6 4 5 4 樣例輸出 17.41 評測用例規模與約定 對於 30% 的評測用例,1 <= n <= 10; 對於 60% 的評測用例,1 <= n <= 100; 對於全部評測用例,1 <= n <= 1000,0 <= x, y, h <= 10000。
經過閱讀題面瞭解到是最小生成樹的模板題。接收完數據後,須要經過題目給出的公式算出兩點之間的權重,結果保存到一個鄰接矩陣裏(稠密圖)。最後使用普里姆算法,設置第一個結點爲起點,求出最小生成樹。最後將全部邊的權值加起來就是答案。輸出能夠使用printf("%.2f")
格式化輸出,最自動四捨五入。ios
#include <iostream> #include <algorithm> #include <cmath> #include <cstdio> #define N 1001 #define WHITE 0 #define GRAY 1 #define BLACK 2 #define INFTY 1 << 21 using namespace std; double M[N][N], d[N]; int color[N], p[N], n; struct Node { double x, y, h; } arr[N]; void prim () { for (int i = 0; i < N; i++) { color[i] = WHITE; d[i] = INFTY; } d[0] = 0; p[0] = -1; int mincost, u; while (1) { mincost = INFTY; for (int i = 0; i < n; i++) { if (color[i] != BLACK && d[i] < mincost) { mincost = d[i]; u = i; } } if (mincost == INFTY) break; color[u] = BLACK; for (int v = 0; v < n; v++) { if (color[v] != BLACK && M[u][v]) { d[v] = M[u][v]; p[v] = u; color[v] = GRAY; } } } } int main () { cin >> n; double x, y, h; for (int i = 0; i < n; i++) { cin >> x >> y >> h; arr[i].x = x; arr[i].y = y; arr[i].h = h; } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i == j) M[i][j] = 0; else { x = (arr[i].x - arr[j].x) * (arr[i].x - arr[j].x); y = (arr[i].y - arr[j].y) * (arr[i].y - arr[j].y); h = (arr[i].h - arr[j].h) * (arr[i].h - arr[j].h); M[i][j] = sqrt(x + y) + h; } } } prim(); double ans = 0; for (int i = 0; i < n; i++) ans += d[i]; printf("%.2f", ans); return 0; }