Say Cheese UVA - 1001 (建圖+floyd)
阿新 • • 發佈:2018-12-26
題意:無限大的乳酪裡有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; }