题目意思:给定n个点,求出点之间的最小的距离之和
解题思路:1 利用单源最短路算法 2 枚举点构成序列的全排列,求出所有排列的中的最小,并且记录下对应点的位置
代码:
//要求单源最短路径,对于这一题我们知道点的个数最多为8,那么我们可以采用枚举每个点的顺序位置,就是去枚举这个点全排列,然后得到最小值,并且保存下序列的位置 #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <list> #include <vector> #include <stack> #include <cmath> #include <algorithm> #define eps 1e-8 using namespace std; const int MAXN = 10010; struct Point { int x; int y; }; Point p[8];//存储点的坐标 int tempsum[50000][8];//保存每一个序列的点的位置 int n, k, mark; double sum; int vis[8];//我们初始化为0-7然后用这个数组的排列来映射点的位置 //输出函数 void output() { int i; int j = mark; double tsum; for (i = 0; i < n - 1; i++) { int ti = tempsum[j][i]; int tj = tempsum[j][i + 1]; tsum = 0.0; double tx = (p[ti].x - p[tj].x)*(p[ti].x - p[tj].x); double ty = (p[ti].y - p[tj].y)*(p[ti].y - p[tj].y); tsum = (sqrt(tx + ty) + 16); printf("Cable requirement to connect (%d,%d) to (%d,%d) is %.2lf feet.\n", p[ti].x, p[ti].y, p[tj].x, p[tj].y, tsum); } printf("Number of feet of cable required is %.2lf.\n", sum); } //处理函数 void solve() { sum = 999999999; k = 0; while (next_permutation(vis, vis + n)) {//全排列 double tempSum = 0.0; for (int i = 0; i < n; i++) tempsum[k][i] = vis[i];//把vis的数组值保存到对应的排列里面 for (int i = 0; i < n - 1; i++) { double tempx = (p[vis[i]].x - p[vis[i + 1]].x) * (p[vis[i]].x - p[vis[i + 1]].x); double tempy = (p[vis[i]].y - p[vis[i + 1]].y) * (p[vis[i]].y - p[vis[i + 1]].y); tempSum += (sqrt(tempx + tempy) + 16); } if (sum > tempSum) {//更新最小的sum,并且记录最小的排列的序号 sum = tempSum; mark = k; } ++k; } } int main() { int cnt = 1; while (scanf("%d%*c", &n) && n) { for (int i = 0; i < n; i++) { scanf("%d%d", &p[i].x, &p[i].y); vis[i] = i; } solve(); printf("**********************************************************\n"); printf("Network #%d\n", cnt); output(); ++cnt; } return 0; }