hdu 1245 Saving James Bond 最短路spfa+简单计算几何

题意:一个人从直径为15米的小岛上踩着鲨鱼跳离湖(好奇怪的题目),湖为100*100的正方形。人最大的跳跃距离为D,给出n个鲨鱼的坐标,求人跳跃的最小距离及在这情况下的跳跃次数。

hdu 1245 Saving James Bond 最短路spfa+简单计算几何_第1张图片

把岛看做点0,湖外看做点n+1,先计算出这n+2个点之间的距离,若超过D则设为不连通,然后再求最短路。用pre数组记录路径,可以求出跳跃次数。注意double及精度,注意如果n==0的情况。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#define N 110
#define INF 1e15
using namespace std;

double x[N],y[N],d[N],mp[N][N],D;
int v[N],pre[N],n;

void spfa(int s,int t)
{
    for(int i=0;i<=n+1;i++)
    {
        d[i]=INF;
        v[i]=0;
        pre[i]=-1;
    }
    queue<int> q;
    q.push(s);
    d[s]=0;
    v[s]=1;
    while(!q.empty())
    {
        int c=q.front();
        q.pop();
        v[c]=0;
        for(int i=0;i<=n+1;i++)
        {
            if(d[i]>d[c]+mp[c][i])
            {
                pre[i]=c;
                d[i]=d[c]+mp[c][i];
                if(!v[i])   v[i]=1,q.push(i);
            }
        }
    }
    if(d[t]>=INF)
    {
        printf("can't be saved\n");
        return;
    }
    int c=t,step=0;
    while(c!=s)
        step++,c=pre[c];
    printf("%.2lf %d\n",d[t],step);
    return;
}

int main()
{
    while(~scanf("%d%lf",&n,&D))
    {
        if(n==0)
        {
            if(D>=42.5) cout<<"42.50 1"<<endl;
            else    cout<<"can't be saved"<<endl;
            continue;
        }
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&x[i],&y[i]);
        x[0]=y[0]=0.0;
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
            {
                mp[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
                if((i||j)&&!(i&&j))  mp[i][j]-=7.5;
                mp[i][j]=max(mp[i][j],0.0);
                if(mp[i][j]>D)   mp[i][j]=INF;
            }
        for(int i=0;i<=n;i++)
        {
            double c=min(50-x[i],50-y[i]);
            c=min(c,min(50+x[i],50+y[i]));
            if(c>D) c=INF;
            mp[i][n+1]=mp[n+1][i]=c;
        }
        spfa(0,n+1);
    }
}

你可能感兴趣的:(C++,最短路,HDU,SPFA,计算几何)