点少,标准的floyed。先用floyed更新出任意两点之间的最短距离。用并查集标记在同一牧场的的点。最后枚举两个不同牧场的点之间的距离len3,以及各自和自己牧场中最远的距离len1,len2.我们求的结果就是最小的(len1+len2+len3)。
然后第七个点一直过不去。后来发现,少考虑了一种情况,就是可能两个原牧场中的某一个直径可能大于len1+len2+len3。。。。。。。。。。找了三个小时
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define res register int
const int maxn=155;
char G[maxn][maxn];
double dis[maxn][maxn];
int fa[maxn];
int N;
struct Node{
double x,y;
}node[maxn];
double cal(int a,int b){
return sqrt(abs(node[a].x-node[b].x)*abs(node[a].x-node[b].x)+abs(node[a].y-node[b].y)*abs(node[a].y-node[b].y));
}
int find(int x){
if(x==fa[x]) return x;
else return fa[x]=find(fa[x]);
}
void unit(int x,int y){
x=find(x);
y=find(y);
if(x!=y) fa[x]=y;
return;
}
void init()
{
cin>>N;
for(res i=1;i<=N;i++){
fa[i]=i;
scanf("%lf%lf",&node[i].x,&node[i].y);
}
for(res i=1;i<=N;i++){
char temp[maxn];
scanf("%s",temp);
sprintf(G[i],"#%s",temp);
}
for(res i=1;i<=N;i++)
for(res j=1;j<=N;j++)
dis[i][j]=inf;
for(res i=1;i<=N;i++){
for(res j=1;j<i;j++){
if('1'==G[i][j]){
unit(j,i);
dis[i][j]=dis[j][i]=cal(i,j);
}
}
}
for(res i=1;i<=N;i++)
dis[i][i]=0;
}
void floyed()
{
for(res k=1;k<=N;k++)
for(res i=1;i<=N;i++)
for(res j=1;j<=N;j++)
dis[i][j]=dis[j][i]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
int main()
{
init();
floyed();
double len=inf;
for(res i=1;i<=N;i++)
for(res j=i+1;j<=N;j++){
double len1=-inf,len2=-inf,len3=-inf;//len1表示的是第一个牧场到该点的距离 len2是第二个 len3表示的是两点之间的距离
if(find(i)!=find(j)){
len3=cal(i,j);
//开始找第i个点所在牧场里面所有的点到i点最大的距离
for(res k=1;k<=N;k++)
if(find(k)==find(i)) len1=max(len1,dis[i][k]);
//开始找第j个点所在牧场里面所有的点到j点最大的距离
for(res k=1;k<=N;k++)
if(find(k)==find(j)) len2=max(len2,dis[j][k]);
len=min(len,len1+len2+len3);
}
}
printf("%.6lf",len);
return 0;
}