USACO 2.4.3 Cow Tours

分析:首先要连在一起修路的这两个牧区,之前是不连通的。其次就是这两个牧区修路之后,相隔最远的两个牧区的距离最小。其实,只要枚举任意不连通的两个牧区在计算这种情况下的最远的距离就好了,然后在这些最远的距离中找到距离最小(题目要求半径最小)的一个就是所求了。关键是在两个不连通的牧区修路之后求牧场的半径呢?假设已将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;
}
 


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值