核心是Floyd求任意两点最短路,如下:
//Floyd算法
void floyd(int n)
{
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
MAP[ ][ ]记录两点间是否有边,并用point_dis[ ][ ]计算出任意两点之间的距离
dis[ ][ ]则是实际有边的两点间的最短路,不存在的即为极大值INF(可用1000000000)
对于每一个点i,扫描所有点j,如果用zui[ i ]记录到点i到它所能达到的最远点的距离
枚举边,如果没有边,则添加,计算更新ans值
/*
ID:xsy97051
LANG:C++
TASK:cowtour
*/
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
#define MAXN 155
#define INF 1000000000
int n;
int X[MAXN],Y[MAXN];
double point_dis[MAXN][MAXN],dis[MAXN][MAXN],zui[MAXN];
bool Map[MAXN][MAXN];
double juli(int x1,int y1,int x2,int y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
void floyd(int n)
{
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
int main()
{
freopen("cowtour.in","r",stdin);
freopen("cowtour.out","w",stdout);
cin>>n;
for(int i=0;i<n;i++)
cin>>X[i]>>Y[i];
for(int i=0;i<n;i++)
{
string st;
cin>>st;
for(int j=0;j<n;j++)
Map[i][j]=st[j]-'0';
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(i==j) { point_dis[i][j]=dis[i][j]=0; continue;}
point_dis[i][j]=juli(X[i],Y[i],X[j],Y[j]);
if(Map[i][j]) dis[i][j]=point_dis[i][j];
else dis[i][j]=INF;
}
floyd(n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(dis[i][j]<INF)
zui[i]=max(zui[i],dis[i][j]);
double ans=INF;
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
if(!Map[i][j] && dis[i][j]==INF)
{
double nowmax=zui[i]+point_dis[i][j]+zui[j];
if(nowmax>=ans) continue;
for(int k=0;k<n;k++) nowmax=max(nowmax, zui[k]);
ans=nowmax;
}
printf("%.6f\n",ans);
return 0;
}