• HDU1245(Saving James Bond)最短路径Floyd


    /*********************************************
    题目大意:
    有一个100*100的正方形湖,湖中间有一个直径为15的圆形小岛;
    有n个点随机分布在这个正方形中;
    一个人要从小岛上跳出湖外,可以跳跃在这些点上;
    人每一步能跳的最大距离为d;
    求能跳出湖外所需的最小的跳跃距离和步数;
    
    算法分析:
    首先计算每个坐标两两间的距离;
    然后找出所有能从小岛上一步跳到的点存入数组s中;
    然后找出所有能一步跳出湖外的点存入数组t中;
    设置两个虚拟的顶点s和t;
    用s与数组s中的所有顶点相连;
    用t与数组t中的所有顶点相连;
    即此题可以转换成求s到t的最短路径;
    
    算法补充:
    在建图的过程中,如果两个顶点之间的距离大于d了;
    即两个顶点之间无法一步到达,所以此时将权值赋为无穷大;
    此题很是有点卡精度,下面的代码GUN C++始终过不了,只能用C++过;
    不知道是sqrt的问题还是double的问题,蛋碎了一地;
    **********************************************/
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    
    const int N=110;
    const double INF=10e8;
    const double eps = 10e-8;
    
    double G[N][N];//建图
    int step[N][N];//计算走的步数
    int s[N];//存放能从小岛上一步跳到的点
    int t[N];//存放能一步跳出湖外的点
    int n;//有效顶点数
    double d;//一步能跳的距离
    
    struct Point
    {
        int x,y;
    } p[N];
    
    double min(double a,double b)
    {
        return a<b?a:b;
    }
    
    double dist(int a,int b)
    {
        return sqrt(double(a*a)+(double)b*b);
    }
    
    void floyd(int n)
    {
        for(int k=0; k<=n; k++)
        {
            for(int i=0; i<=n; i++)
            {
                for(int j=0; j<=n; j++)
                {
                    if(G[i][j]-G[i][k]-G[k][j]>eps)
                    {
                        G[i][j]=G[i][k]+G[k][j];
                        step[i][j]=step[i][k]+step[k][j];
                    }
                }
            }
        }
    }
    
    void solve()
    {
        if(n==1)//没有符合题意的点
        {
            if(d-42.50>=eps)//直接一步可以从小岛跳出湖外
                puts("42.50 1");
            else
                puts("can't be saved");
            return;
        }
    
        for(int i=0; i<=n; i++)
            for(int j=0; j<=n; j++)
            {
                G[i][j]=INF;
                step[i][j]=0;
            }
    
        for(int i=1; i<n; i++)
        {
            for(int j=1; j<n; j++)
            {
                if(i==j)
                {
                    G[i][j]=0;
                    continue;
                }
                G[i][j]=G[j][i]=dist(p[i].x-p[j].x,p[i].y-p[j].y);
                step[i][j]=step[j][i]=1;
                if(G[i][j]-eps>d)//两根柱子无法一步跳过去
                {
                    G[i][j]=G[j][i]=INF;
                    step[i][j]=step[j][i]=0;
                }
            }
        }
    
        int len1=0;//能从小岛上一步跳到的点的个数
        int len2=0;//能一步跳出湖外的点的个数
        for(int i=1; i<n; i++)
        {
            if(dist(p[i].x,p[i].y)-7.50-d<=eps)//能从小岛上一步跳到的点
            {
                s[len1]=i;
                len1++;
            }
            if((p[i].x*1.0+d-50.00>=eps)||(p[i].x*1.0-d+50.00<=eps)||(p[i].y*1.0-d+50.00<=eps)||(p[i].y*1.0+d-50.00>=eps))//能一步跳出湖外的点
            {
                t[len2]=i;
                len2++;
            }
        }
    
        for(int i=0; i<len1; i++)//初始化虚拟顶点0
        {
            G[s[i]][0]=G[0][s[i]]=dist(p[s[i]].x,p[s[i]].y)-7.5;
            step[s[i]][0]=step[0][s[i]]=1;
        }
        for(int i=0; i<len2; i++)//初始化虚拟顶点n
        {
        	G[t[i]][n]=G[t[i]][n]=min(fabs(abs(p[t[i]].x)-50.00+eps),fabs(abs(p[t[i]].y)-50.00)+eps); //能一步跳出湖外的点的最小值
            step[n][t[i]]=step[t[i]][n]=1;
        }
    
        floyd(n);
        if(fabs(G[0][n]-INF)<eps)
            puts("can't be saved");
        else
            printf("%.2lf %d\n",G[0][n],step[0][n]);
    }
    
    int main()
    {
        //freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin);
        while(~scanf("%d%lf",&n,&d))
        {
            int j=1;
            for(int i=1; i<=n; i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                if(abs(x)*1.0-7.5<=eps&&abs(y)*1.0-7.5<=eps)//点在小岛内
                    continue;
                if(abs(x)*1.0-50>=eps&&abs(y)*1.0-50>=eps)//点在小岛外
                    continue;
                p[j].x=x;
                p[j].y=y;
                j++;
            }
            n=j;
            solve();
        }
        return 0;
    }
    


  • 相关阅读:
    处理缺失值
    数据清理
    数据聚合
    ajax动态生成table
    MangeEmpHashMap
    Arraylist的雇员管理操作
    jsp获取一个对象和list对象
    Controller比较两个对象discs、outlets中的元素是否相等。相同则相应的checkbox为checked
    限制input text输入的类型(数字,字母,小数点)
    联合主键的映射运用
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3014030.html
Copyright © 2020-2023  润新知