题意:无限大的奶酪里有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;
}