Uva1001 Say Cheese Floyd
题意:一个无限大的奶酪里有n个球形的洞,在洞内可以瞬移,不然每一个单位要用10sec,现在给定起始点和结束点,问最短需要耗时多久?
思路:把球形的洞当做是节点,两点之间的距离是两者球心的距离减去两者的半径,因为n<=100,所以可以用floyd算法来解决。但是需要注意有可能两个球相交,所以要考虑这种情况
#include <stdio.h> #include <string.h> #include <math.h> #include <queue> #include <map> #include <vector> #include <algorithm> #include <iostream> using namespace std; #define inf 0x3f3f3f3f typedef long long ll; const int maxn=105; #define rep(i,n) for(int i=1;i<=(n);i++) int n; int x[maxn],y[maxn],z[maxn],r[maxn]; double dp[maxn][maxn]; double dis(int x1,int x2,int y1,int y2,int z1,int z2,int r1,int r2){ double res=sqrt(1.0*(x1-x2)*(x1-x2)+1.0*(y1-y2)*(y1-y2)+1.0*(z1-z2)*(z1-z2))-r1-r2; if(res>0)return res; else return 0; } void init(){ memset(dp,inf,sizeof(dp)); rep(i,n+2){ for(int j=i+1;j<=n+2;j++){ dp[i][j]=dp[j][i]=dis(x[i],x[j],y[i],y[j],z[i],z[j],r[i],r[j]); } } } void floyd(){ rep(k,n+2){ rep(i,n+2){ rep(j,n+2){ if(i!=j){ dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]); } } } } } int main(){ int cas=1; while(scanf("%d",&n)==1&&n!=-1){ rep(i,n)scanf("%d%d%d%d",&x[i],&y[i],&z[i],&r[i]); for(int i=n+1;i<=n+2;i++){ scanf("%d%d%d",&x[i],&y[i],&z[i]); r[i]=0; } init(); floyd(); double res=dp[n+1][n+2]*10; printf("Cheese %d: Travel time = %.0f sec\n",cas,res); cas++; } return 0; }