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;
}

 

posted @ 2018-04-26 14:27  87hbteo  阅读(120)  评论(0编辑  收藏  举报