dij算法理解

(不能有负权边)
!长度步数显示法!
集合1:已最短点集合
集合2:未最短点到源点距离集合
第一开始把和源点连接的点的距离排序起来
那么2里最小的一定是源点到这个点的最短路径
因为从源点如果想到这个点有一条其它更短路径
那么这个路径只能是1集合到这个点,如果从2集合就已经更长了
而集合1里到这个点的路径已经被松弛过了是最短的

接下来再往下松弛(用当前节点更新别的节点的距离)
那么2里最小的,一定是源点到这个点的最短路径
因为从源点出发,如果不是经历的当前同样路径,想更短
那么这个路径只能是1集合到这个点,如果2集合就已经更长了
而集合1里到这个点的路径已经被松弛过了是最短的

1:dij本质上其实是贪心
2:不可能用比当前最短的路径长的路径去更新别的路径
3:每次都会找到一个最短的路径

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int main()
{
    int N,M,A,B,C,temp;
    int dis[105],mp[105][105];
    bool vis[105];
    while((N=read())&&(M=read()))
    {
        for(int i=1;i<=N;i++)
            for(int j=1;j<=N;j++)
                mp[i][j]=10000000;
        for(int i=1;i<=N;i++) dis[i]=10000000;
        for(int i=1;i<=N;i++) vis[i]=0;
        dis[0]=10000000; //!!!!!!!!!!!
        dis[1]=0;
        for(int i=1;i<=M;i++)
        {
            A=read(); B=read(); C=read();
            if(mp[A][B]>C) mp[A][B]=C;
            if(mp[B][A]>C) mp[B][A]=C;
        }
        for(int i=1;i<=N;i++)
        {
            temp=0;
            for(int i=1;i<=N;i++)
            {
                if(!vis[i]&&dis[i]<dis[temp]) temp=i;
            }
            vis[temp]=1;
            if(temp==N) break;
            for(int i=1;i<=N;i++)
            {
                if(dis[temp]+mp[temp][i]<dis[i]) dis[i]=dis[temp]+mp[temp][i];
            }
        }
        printf("%d\n",dis[N]);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,确定选址的问题可以转化为在三维曲面上求最短路径。这里可以使用Dijkstra算法来求解最短路径问题。 首先,我们需要定义一个三维曲面,可以使用三个一维数组(x, y, z)来表示。然后,我们需要定义一个邻接矩阵来表示曲面上的点和边的连接关系,即哪些点之间有边相连。对于这个问题,我们可以将曲面上的点看做图中的节点,将曲面上的边看做图中的边,然后用邻接矩阵表示节点之间的连接关系。 接下来,我们可以用Dijkstra算法来求解最短路径。Dijkstra算法是一种贪心算法,从起点开始,依次寻找到每个节点的最短路径,并将这个节点标记为已访问。在每次寻找下一个最短路径时,我们需要更新起点到该节点的距离,并标记该节点的前一个节点,以便最后回溯路径。 下面是一个简单的Python实现,假设我们已经有了一个三维曲面的点集和邻接矩阵,这里假设邻接矩阵为一个二维数组,元素为每条边的权重,若两个点之间没有直接相连的边,则权重为无穷大。 ```python import numpy as np def dijkstra(start, end, adj_matrix): """ Dijkstra算法求解最短路径 :param start: 起点 :param end: 终点 :param adj_matrix: 邻接矩阵 :return: 最短路径的长度和路径上的节点 """ n = len(adj_matrix) visited = [False] * n distance = [np.inf] * n path = [-1] * n distance[start] = 0 for i in range(n): # 找到当前未访问节点中距离起点最近的节点 min_dist = np.inf index = -1 for j in range(n): if not visited[j] and distance[j] < min_dist: min_dist = distance[j] index = j visited[index] = True # 更新该节点的邻居节点的距离 for k in range(n): if not visited[k] and adj_matrix[index][k] != np.inf: new_dist = min_dist + adj_matrix[index][k] if new_dist < distance[k]: distance[k] = new_dist path[k] = index # 回溯路径 shortest_path = [end] cur = end while cur != start: cur = path[cur] shortest_path.append(cur) shortest_path.reverse() return distance[end], shortest_path ``` 使用这个函数,我们可以求解出任意两个点之间的最短路径,从而确定选址。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值