分析:首先要连在一起修路的这两个牧区,之前是不连通的。其次就是这两个牧区修路之后,相隔最远的两个牧区的距离最小。其实,只要枚举任意不连通的两个牧区在计算这种情况下的最远的距离就好了,然后在这些最远的距离中找到距离最小(题目要求半径最小)的一个就是所求了。关键是在两个不连通的牧区修路之后求牧场的半径呢?假设已将one牧区种的D和two牧区中的F相连,想一下,这个牧场的半径是不是等于与D相距最远的点到D的距离+D与F的距离+与F相距最远的点的距离呢?这样的求法是满足题目所说的牧场的半径是相距最远的两个点的距离。所以思路很快就出来了:1.用floyed计算任意两点间的距离2.计算每个点与其他点的最远距离3.计算任意两个不连通的点修路之后牧场的半径。
源代码:
/*
ID: supersnow0622
PROG: cowtour
LANG: C++
*/
#include<iomanip>
#include <iostream>
#include <fstream>
#include <string>
#include<math.h>
#include<memory.h>
using namespace std;
struct Point
{
int x,y;
};
Point p[160];
double map[160][160];
double maxDis[160];
double getDistance(Point p1,Point p2)
{
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
int main() {
ofstream fout ("cowtour.out");
ifstream fin ("cowtour.in");
memset(map,0,sizeof(map));
memset(maxDis,0,sizeof(maxDis));
int N;
char a;
double temp,minDis=100000;
cin>>N;
for(int i=1;i<=N;i++)
cin>>p[i].x>>p[i].y;
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
{
cin>>a;
if(i!=j)
{
if(a=='0')
map[i][j]=100000;
else
map[i][j]=getDistance(p[i],p[j]);
}
}
for(int k=1;k<=N;k++)
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
if(map[i][k]+map[k][j]<map[i][j])
map[i][j]=map[i][k]+map[k][j];
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
if(map[i][j]>maxDis[i]&&map[i][j]!=100000)
maxDis[i]=map[i][j];
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
if(map[i][j]==100000)
{
temp=getDistance(p[i],p[j])+maxDis[i]+maxDis[j];
if(temp<minDis)
minDis=temp;
}
for(int i=1;i<=N;i++)
if(maxDis[i]>minDis)
minDis=maxDis[i];
cout<<setprecision(6)<<setiosflags(ios::fixed)<<minDis;
return 0;
}