牛的旅行 Cow Tours

P1522 牛的旅行 Cow Tours
题目概述:有的路径连接一些特定的牧区。一片所有连通的牧区称为一个牧场。但是就目前而言,你能看到至少有两个牧区通过任何路径都不连通。在牧场里添加一条路径(注意,恰好一条)。对这条路径有以下限制:一个牧场的直径就是牧场中最远的两个牧区的距离(本题中所提到的所有距离指的都是最短的距离)。请编程找出一条连接两个不同牧场的路径,使得连上这条路径后,这个更大的新牧场有最小的直径。输出在所有牧场中最小的可能的直径。
数据规模:N (1 <= N <= 150),X,Y (0 <= X ,Y<= 100000)
思路:这个题首先要预处理距离,用勾股定理,然后考虑到N的值比较小(事实上小于300就可以了),我们考虑用O(N^3)的Floyd算法,然后如果暴力枚举一次就是O(N^2)*O(N^3)的时间,就算N再小也不能用这种算法,所以考虑是求一个最值,所以用最大值来记录,这样时间变为O(N^2),就可以过了。
代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int x[155],y[155];
double a[155][155];
int temp;
int i,j,k,n,t,m;
double maxx,minn=10000000000;
int b[155];
double c[155][155];

int rr()
{
    int ans=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        ans*=10;
        ans+=ch-'0';
        ch=getchar();
    }
    return ans*f;
}

double dis(int xx,int yy)
{
    return sqrt((x[xx]-x[yy])*(x[xx]-x[yy])
    +(y[xx]-y[yy])*(y[xx]-y[yy]));
}

void solve()
{
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        for(int k=1;k<=n;k++)
        {
        if(a[i][j]>a[i][k]+a[k][j])
        a[i][j]=a[i][k]+a[k][j];
        }
    }
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        for(int k=1;k<=n;k++)
        {
        if(a[i][j]>a[i][k]+a[k][j])
        a[i][j]=a[i][k]+a[k][j];
        }
    }
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    if(a[i][j]!=1000000000)
    maxx=max(maxx,a[i][j]);

    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    a[i][j]=c[i][j];

}

int main()
{
    n=rr();
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    a[i][j]=1000000000;
    char ch;
    for(i=1;i<=n;i++)
    x[i]=rr(),y[i]=rr();
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    {
        cin>>ch;
        if(ch=='1')
        a[i][j]=a[j][i]=dis(i,j);
    }

    for(i=1;i<=n;i++)
    a[i][i]=0;

    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    for(k=1;k<=n;k++)
    {
        if(a[i][j]>a[i][k]+a[k][j])
        a[i][j]=a[i][k]+a[k][j];
    }

    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    c[i][j]=a[j][i];

    for(int i=1;i<=n;i++)
    for(int j=1;j<i;j++)
    {
        if(a[i][j]==1000000000)
        {
            maxx=0;
            a[i][j]=a[j][i]=dis(i,j);
            solve();
            minn=min(minn,maxx);
            a[i][j]=a[j][i]=1000000000;
        }
    }
    printf("%.6f",minn);
    return 0;
}
/*

*/

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值