题目意思:给定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;
}