乍一看,像最小生成树,实际不用,因为数据量较小(最大8台电脑),所以直接模拟全排列算最小值就可以。
代码如下:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
struct point
{
int x, y;
} po[10];
int n;
double save_d[10], dis[10], tot, dd;
int max_[10], save_v[10], vis[10];
int solve(int cur, double d)
{
if(cur == n)
{
if(d < tot)
{
tot = d;
for(int i = 0; i < n; i++)
{
save_d[i] = dis[i];
max_[i] = save_v[i];
}
}
return 1;
}
for(int i = 0; i < n; i++)
if(!vis[i])
{
if(cur)
{
double ans1, ans2;
ans1 = (double)(po[i].x - po[save_v[cur - 1]].x);
ans2 = (double)(po[i].y - po[save_v[cur - 1]].y);
dd = sqrt(ans1 * ans1 + ans2 * ans2);
dis[cur - 1] = dd;
}
else
dd = 0;
if(d + dd > tot) // 若中间过程中路程和已经大于已知的最小值,则直接忽略此种排列情况
continue;
vis[i] = 1;
save_v[cur] = i;
solve(cur + 1, d + dd);
vis[i] = 0;
}
return 0;
}
int main()
{
#ifdef test
freopen("sample.txt", "r", stdin);
#endif
int num = 1;
while(scanf("%d", &n), n)
{
tot = 1000000;
memset(vis, 0, sizeof(vis));
for(int i = 0; i < n; i++)
scanf("%d%d", &po[i].x, &po[i].y);
solve(0, 0);
printf("**********************************************************\n");
printf("Network #%d\n", num++);
for(int i = 0; i < n - 1; i++)
printf("Cable requirement to connect (%d,%d) to (%d,%d) is %.2lf feet.\n", po[max_[i]].x, po[max_[i]].y, po[max_[i + 1]].x, po[max_[i + 1]].y, save_d[i] + 16);
printf("Number of feet of cable required is %.2lf.\n", tot + (n - 1) * 16);
}
return 0;
}