• 关于最短路算法的学习


    对prim算法和dijk算法搞混了

    归根结底还是对算法的理解不够透彻

    先写一道变型dijk算法

    Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sitting on another stone. He plans to visit her, but since the water is dirty and full of tourists' sunscreen, he wants to avoid swimming and instead reach her by jumping. 
    Unfortunately Fiona's stone is out of his jump range. Therefore Freddy considers to use other stones as intermediate stops and reach her by a sequence of several small jumps. 
    To execute a given sequence of jumps, a frog's jump range obviously must be at least as long as the longest jump occuring in the sequence. 
    The frog distance (humans also call it minimax distance) between two stones therefore is defined as the minimum necessary jump range over all possible paths between the two stones. 

    You are given the coordinates of Freddy's stone, Fiona's stone and all other stones in the lake. Your job is to compute the frog distance between Freddy's and Fiona's stone. 

    Input

    The input will contain one or more test cases. The first line of each test case will contain the number of stones n (2<=n<=200). The next n lines each contain two integers xi,yi (0 <= xi,yi <= 1000) representing the coordinates of stone #i. Stone #1 is Freddy's stone, stone #2 is Fiona's stone, the other n-2 stones are unoccupied. There's a blank line following each test case. Input is terminated by a value of zero (0) for n.

    Output

    For each test case, print a line saying "Scenario #x" and a line saying "Frog Distance = y" where x is replaced by the test case number (they are numbered from 1) and y is replaced by the appropriate real number, printed to three decimals. Put a blank line after each test case, even after the last one.

    Sample Input

    2
    0 0
    3 4
    
    3
    17 4
    19 4
    18 5
    
    0
    

    Sample Output

    Scenario #1
    Frog Distance = 5.000
    
    Scenario #2
    Frog Distance = 1.414

    明显的最短路算法

    对于dijk说一下原理

    对于一个图将其分为v e

    v表示已经确定由起点到达该店的最短最短路

    e表示还未确定

    首先将起点放入

    先写一个普通最短路

    再写一个堆优化的最短路(此题也能堆优化)

    于prim算法不同的是prim算法算法更新的dis是当前的最小边的长度

    关于dijk为什么无法处理负环的问题

    https://blog.csdn.net/blink_invoker/article/details/27181285

    简单粗暴的最短路算法

    bellman ford

    https://www.cnblogs.com/lxt1105/p/6477639.html

    可解决负权边问题 同样是否可以判定负权环

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<string>
    #include<iostream>
    #include<list>
    #include<stack>
    #include<deque>
    #include<cstring>
    #include<cmath>
    using namespace std;
    pair<double,double> a[1005];
    double dis[1005];
    int vis[1005];
    inline double  distant(int x,int y)
    {
        return sqrt((a[x].first-a[y].first)*(a[x].first-a[y].first)+(a[x].second-a[y].second)*(a[x].second-a[y].second));
    }
    int main()
    {
        int n;
        int cas=0;
        double temp1,temp2;
        while(~scanf("%d",&n))
        {
            cas++;
            if(n==0) break;
            memset(vis,0,sizeof(vis));
            memset(dis,-1,sizeof(dis));
            for(int i=1; i<=n; i++)
            {
                scanf("%lf%lf",&temp1,&temp2);
                a[i]=make_pair(temp1,temp2);
            }
            double MIN;
            int k;
            for(int i=1;i<=1000;i++) dis[i]=1e9+1;
            dis[1]=0;
            for(int i=1; i<n; i++)
            {
                MIN=1e9;
                for(int j=1; j<=n; j++)
                {
                    if(vis[j]==0&&MIN>dis[j])
                    {
                        MIN=dis[j];
                        k=j;
                    }
                }//选择当前由v中到e的最近的点 由贪心保证正确性
                if(vis[k]==1) break;
                vis[k]=1;//将该点加入到集合v
           
                for(int j=1; j<=n; j++)
                {
                    if(dis[j]>max(dis[k],distant(k,j)))
                    {
                        dis[j]=max(dis[k],distant(k,j));
                    }
                }//用最新加入v的点来松弛到所有点的距离
            }
            printf("Scenario #%d
    ",cas);
            printf("Frog Distance = %.3lf
    
    ",dis[2]);
    
        }
    }
    
    ​
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<string>
    #include<iostream>
    #include<list>
    #include<stack>
    #include<deque>
    #include<cstring>
    using namespace std;
    struct node
    {
        int to;
        int w;
        int nex;
        bool operator > (const node temp) const
        {
            return w>temp.w;
        }
    }a[10005];
    int first[10005];
    int dis[10005];
    int vis[10005];
    priority_queue< node, vector<node> ,greater<node> > q;
    int main()
    {
        //freopen("in.txt","r",stdin);
        int tmp1,tmp2,tmp3;
        memset(a,-1,sizeof(0));
        memset(first,-1,sizeof(first));
        memset(vis,-1,sizeof(vis));
        memset(dis,0x3f,sizeof(dis));
        int t,n;
        scanf("%d%d",&t,&n);
        int cnt=1;
        for(int i=1;i<=t;i++)
        {
    //链式前向星存图first代表当前权值 second代表目标点
            scanf("%d%d%d",&tmp1,&tmp2,&tmp3);
            a[cnt].nex=first[tmp1];
            a[cnt].to=tmp2;
            a[cnt].w=tmp3;
            first[tmp1]=cnt;
            cnt++;
            a[cnt].nex=first[tmp2];
            a[cnt].to=tmp1;
            a[cnt].w=tmp3;
            first[tmp2]=cnt;
            cnt++;
        }
        dis[1]=0;
        node temp;
        temp.to=1;
        temp.w=0;
        temp.nex=0;
        q.push(temp);//将起点加入到v中
        while(q.size())
        {
            node temp2;
            temp=q.top();
            q.pop();
            if(vis[temp.to]==1) continue;
            vis[temp.to]=1;//将堆顶元素加入到集合v中
            for(int i=first[temp.to];i!=-1;i=a[i].nex)
            {
                if(dis[a[i].to]>dis[temp.to]+a[i].w)
                {//若满足松弛条条件将该点松弛并将松弛后的点的新距离加入到堆中
                    dis[a[i].to]=dis[temp.to]+a[i].w;
                    temp2.w=dis[a[i].to];
                    temp2.to=a[i].to;
                    q.push(temp2);
                }
            }
           // cout<<endl;
        }
        printf("%d
    ",dis[n]);
    }
    
    ​

    对于堆优化的dijk的算法 我们只需要把每一个松弛过的边 加入到堆中 最后将堆遍历完即可

  • 相关阅读:
    C++并发与多线程学习笔记--unique_lock详解
    C++并发与多线程学习笔记--互斥量、用法、死锁概念
    MongoDB教程--配置与入门
    C++并发与多线程学习笔记--多线程数据共享问题
    C++并发与多线程学习笔记--参数传递详解
    C++并发与多线程学习笔记--基本概念和实现
    Python学习笔记--语音处理初步
    C#中三个关键字params,Ref,out
    Windows窗体应用开发3--配置标准控件1
    在博客的第一天
  • 原文地址:https://www.cnblogs.com/caowenbo/p/11852319.html
Copyright © 2020-2023  润新知