Say Cheese UVA - 1001 (建图+floyd)

传送门

题意:无限大的奶酪里有n个球形的洞,帮助小老鼠A用最短的时间到达小老鼠O的所在位置,奶酪里的移动速度为10秒一个单位,但是在洞里可以瞬间移动,洞和洞可以相交,输入n个球的位置和半径,以及A和O的坐标,求最短时间。

题解:把起点A和终点O都看成是半径为0的球,共有n+2个球,每个球的球心看成结点,若两个球(p1,r1)和(p2,r2)所对应的结点之间的距离为d=|p1-p2|-r1-r2,如果d<0,说明两个球相交,认为相应的距离为0。求出所有的距离之后,任意两个球对应结点之间都有一个距离为d的无向边,使用floyd算法可以求出A和O的最短距离。

附上代码:


#include<bits/stdc++.h>

using namespace std;

const int maxn=1e2+50;
const double eps=1e-8;

double d[maxn][maxn];

struct Point{
    double x,y,z;
    Point(double _x=0,double y=0,double z=0):x(x),y(y),z(z){}
};

double length(Point a,Point b)
{
    double ans=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z);
    return sqrt(ans);
}

int dcmp(double ans)
{
    if(fabs(ans)<eps){
        return 0;
    }else{
        return ans<0?-1:1;
    }
}

struct Sphere{
    Point center;double radius;
};
Sphere S[maxn];

double Distance(Sphere a,Sphere b)
{
    double ans=length(a.center,b.center)-a.radius-b.radius;
    if(dcmp(ans)<0){
        ans=0;
    }
    return ans*10;
}

int main()
{
    int n,t=1;
    while(scanf("%d",&n)==1&&n>0){
        for(int i=0;i<n;i++){
            scanf("%lf%lf%lf%lf",&S[i].center.x,&S[i].center.y,&S[i].center.z,&S[i].radius);
        }
        scanf("%lf%lf%lf",&S[n].center.x,&S[n].center.y,&S[n].center.z);
        S[n].radius=0;
        n++;
        scanf("%lf%lf%lf",&S[n].center.x,&S[n].center.y,&S[n].center.z);
        S[n].radius=0;
        n++;
        for(int i=0;i<n;i++){
            d[i][i]=0;
            for(int j=i+1;j<n;j++){
                d[i][j]=d[j][i]=Distance(S[i],S[j]);
            }
        }
        for(int k=0;k<n;k++){
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
                }
            }
        }
        printf("Cheese %d: Travel time = %.0lf sec\n",t++,d[n-1][n-2]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/85251931