问题描述
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。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <iomanip>
using namespace std;
int n;//边的数量
class village;
class edge;
vector<village> v_arr;
vector<edge> e_arr;
class village {
public:
double x, y, h;
village(int xx, int yy, int hh)
:x(xx), y(yy), h(hh) {}
};
class edge {
public:
int s, e;//边的连接的两个村庄的编号-1
double cost;//连接的花费
edge(int start, int end) {
s = start;
e = end;
double x_1 = v_arr[s].x, y_1 = v_arr[s].y, h_1 = v_arr[s].h;
double x_2 = v_arr[e].x, y_2 = v_arr[e].y, h_2 = v_arr[e].h;
cost = 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);
}
};
double prim(int start) {
int k = 0;//已连接边的数量
double ans = 0;
int e_num = e_arr.size();//边的总数
vector<int> e_vis(e_num, 0);//记录边是否被访问
vector<int> p_vis(n, 0);//记录点是否被访问
p_vis[start] = 1;
while (k < n - 1) {
double minval = 9999999999999;
int index=-1;
//遍历边集
for (int i = 0; i < e_arr.size(); i++) {
if (e_vis[i] == 0 && p_vis[e_arr[i].s] + p_vis[e_arr[i].e] == 1) {//0+1||1+0
if (e_arr[i].cost < minval) {//有更小的花费就更新
minval = e_arr[i].cost;
index = i;
}
}
}
ans += minval;
//访问标记
e_vis[index] = 1;
p_vis[e_arr[index].s] = 1;
p_vis[e_arr[index].e] = 1;
k++;
}
return ans;
}
int main() {
int x, y, h;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> x >> y >> h;
v_arr.push_back(village(x, y, h));
}
//边的数量
// int e_num = (1+(n-1))*(n-1)/2;
int e_num = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
e_arr.push_back(edge(i, j));
}
}
cout << setprecision(2) << fixed << prim(0) << endl;
return 0;
}
转载:https://blog.csdn.net/mu_mu_mu_mu_mu/article/details/105719571