0
点赞
收藏
分享

微信扫一扫

图的最短路径算法——弗洛伊德算法和迪杰斯特拉算法

软件共享软件 2022-02-23 阅读 61

例1:下面是城市的地图,注意是单向图,求城市1到城市5的最短距离。(引用的是上次总结的图论(一)中1)的例2)(来源于qibofang)

       弗洛伊德算法原理:依次以每一点为中心点,带入图中的所有边中,通过比较ege[i][j]>ege[i][k]+ege[k][j]的大小来得到两点间最小的边,依次以每一点循环后比较后即可得到所有点到点之间的最短路径。

下面是弗洛伊德算法解题代码:

#include<bits/stdc++.h>
using namespace std;

#define inf 999999999
#define LL long long
long long yue[1000]={0};


int ege[10][10];

//深度搜索dfs,需要定义一个最短路径,一个访问标记点
int n=5,m=8,miniPath=inf,mark[8]={0};
void dfs(int cur,int dst){
//出口条件,满足寻找到最后一个点的时候
    if(cur==n){
        //for(int i=1;i<=5;i++){
        //    cout<<mark[i];
        //}
        //cout<<dst<<endl;
        if(miniPath>dst)
            miniPath=dst;
        else
            return;
    }
//如果是大于的话就直接返回,无效路
    if(dst>miniPath)
        return;
    else
    for(int i=1;i<=n;i++){
//如果此路可走下去,则继续往下面走
        if(ege[cur][i]!=inf&&mark[i]==0&&ege[cur][i]!=0){
            mark[i]=1;
            dfs(i,dst+ege[cur][i]);
//结束后置为未访问
            mark[i]=0;
        }
    }
}

void print(){
  for(int i=1;i<=n;i++){
    for(int j=1;j<=n;j++)
    printf("%d ",ege[i][j]);
    cout<<endl;
  }
}

//以一个中间点为过度,来判断两点间的距离是否为最小,循环遍历每一个点
void floyd(){
   for(int k=1;k<=n;k++){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(ege[i][k]!=inf&&ege[k][j]!=inf&&ege[i][j]>ege[i][k]+ege[k][j])
                ege[i][j]=ege[i][k]+ege[k][j];
        }
    }
   }
}

int main()
{
   for(int i=1;i<=5;i++){
    for(int j=1;j<=5;j++){
        ege[i][j]=inf;
    }
    ege[i][i]=0;
   }
 ege[1][2]=2;ege[1][5]=10;
 ege[2][3]=3;ege[2][5]=7;
 ege[3][1]=4;ege[3][4]=4;
 ege[4][5]=5;
 ege[5][3]=3;
 mark[1]=1;
 print();

floyd();

print();
cout<<ege[1][n];

}

       这里涉及到了求最小公约数的算法思路,使用到了欧几里得算法,如果两个数不断相模后所得的数,最终到0,则这个数为最小公约数。

       同理,如果想求最小公倍数,只需先求出两个数的最小数,然后两数相乘再除以公约数既为最小公倍数。

      下面是使用迪杰斯特拉算法解决蓝桥杯算法题中的路径问题代码。

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;

#define inf -1
#define LL long long

int line[2050][2050];
int go[2050]= {0};
long long dst[2050]= {0};

int lowa(int la,int lb)
{
    if(lb==0)
        return la;
    else
    {
        lowa(lb,la%lb);
    }
}

void print()
{
    for(int i=1; i<=50; i++)
    {
        cout<<dst[i]<<" ";
    }
    cout<<endl;
}

int high(int m,int n)
{
    return m*n/lowa(m,n);
}

int main()
{
    for(int i=1; i<=2021; i++)
    {
        for(int j=1; j<=2021; j++)
        {
            if(abs(i-j)<=21)
            {
                line[i][j]=high(i,j);
                line[j][i]=line[i][j];
            }
            else
            {
                line[i][j]=inf;
                line[j][i]=inf;
            }
        }
    }

    //初始化dst列表为第一行
    for(int i=1; i<=2021; i++)
    {
        dst[i]=line[1][i];
    }

    int cur=1;
    go[cur]=1;

    for(int k=1; k<=2021; k++)
    {
        long long min=0;
//找一行内的最小值
        for(int i=1; i<=2021; i++)
        {
            if(go[i]==0&&dst[i]!=inf&&(dst[i]<min||min==0))
            {
                min = dst[i];
                cur = i;
            }
        }


        go[cur]=1;
//更新dst数组
        for(int i=1; i<=2021; i++)
        {
            if(go[i]==0&&line[cur][i]!=inf&&(dst[i]>(dst[cur]+line[cur][i])||dst[i]==inf))
                dst[i] = dst[cur]+line[cur][i];
        }
        cout<<cur<<endl;
        //print();
    }

    print();
    cout<<dst[2021];



}

举报

相关推荐

0 条评论