• 基于Yen算法的k最短路径问题的python实现


    老规矩,先上代码

    #date:2021-5-17
    #author:Linuas
    #b站:会武术的白猫
    import copy
    
    def Dijkstra(network,s,d):#迪杰斯特拉算法算s-d的最短路径,并返回该路径和代价
        #print("Start Dijstra Path……")
        path=[]#s-d的最短路径
        n=len(network)#邻接矩阵维度,即节点个数
        fmax=9999999
        w=[[0 for i in range(n)]for j in range(n)]#邻接矩阵转化成维度矩阵,即0→max
        book=[0 for i in range(n)]#是否已经是最小的标记列表
        dis=[fmax for i in range(n)]#s到其他节点的最小距离
        book[s-1]=1#节点编号从1开始,列表序号从0开始
        midpath=[-1 for i in range(n)]#上一跳列表
        u=s-1
        for i in range(n):
            for j in range(n):
                if network[i][j]!=0:
                    w[i][j]=network[i][j]#0→max
                else:
                    w[i][j]=fmax
                if i==s-1 and network[i][j]!=0:#直连的节点最小距离就是network[i][j]
                    dis[j]=network[i][j]
        for i in range(n-1):#n-1次遍历,除了s节点
            min=fmax
            for j in range(n):
                if book[j]==0 and dis[j]<min:#如果未遍历且距离最小
                    min=dis[j]
                    u=j
            book[u]=1
            for v in range(n):#u直连的节点遍历一遍
                if dis[v]>dis[u]+w[u][v]:
                    dis[v]=dis[u]+w[u][v]
                    midpath[v]=u+1#上一跳更新
        j=d-1#j是序号
        path.append(d)#因为存储的是上一跳,所以先加入目的节点d,最后倒置
        while(midpath[j]!=-1):
            path.append(midpath[j])
            j=midpath[j]-1
        path.append(s)
        path.reverse()#倒置列表
        #print(path)
        #print(midpath)
        #print(dis)
        return path
    
    def return_path_sum(network,path):
        result=0
        for i in range(len(path)-1):
            result+=network[path[i]-1][path[i+1]-1]
        return result
    
    def add_limit(path,s):#path=[[[1,3,4,6],5],[[1,3,5,6],7],[[1,2,4,6],8]
        result=[]
        for item in path:
            if s in item[0]:
                result.append([s,item[0][item[0].index(s)+1]])
        result=[list(r) for r in list(set([tuple(t) for t in result]))]#去重
        return result
    
    def return_shortest_path_with_limit(network,s,d,limit_segment,choice):#limit_segment=[[3,5],[3,4]]
        mid_net=copy.deepcopy(network)
        for item in limit_segment:
            mid_net[item[0]-1][item[1]-1]=mid_net[item[1]-1][item[0]-1]=0
        s_index=choice.index(s)
        for point in choice[:s_index]:#s前面的点是禁用点
            for i in range(len(mid_net)):
                mid_net[point-1][i]=mid_net[i][point-1]=0
        mid_path=Dijkstra(mid_net,s,d)
        return mid_path
    
    def judge_path_legal(network,path):
        for i in range(len(path)-1):
            if network[path[i]-1][path[i+1]-1]==0:
                return False
        return True
    
    def k_shortest_path(network,s,d,k):
        k_path=[]#结果列表
        alter_path=[]#备选列表
        kk=Dijkstra(network,s,d)
        k_path.append([kk,return_path_sum(network,kk)])
        while(True):
            if len(k_path)==k:break
            choice=k_path[-1][0]
            for i in range(len(choice)-1):
                limit_path=[[choice[i],choice[i+1]]]#限制选择的路径
                if len(k_path)!=1:
                    limit_path.extend(add_limit(k_path[:-1],choice[i]))
                mid_path=choice[:i]
                mid_res=return_shortest_path_with_limit(network,choice[i],d,limit_path,choice)
                if judge_path_legal(network,mid_res):
                    mid_path.extend(mid_res)
                else:
                    continue
                mid_item=[mid_path,return_path_sum(network,mid_path)]
                if mid_item not in k_path and mid_item not in alter_path:
                    alter_path.append(mid_item)
            if len(alter_path)==0:
                print("总共只有{}条最短路径!".format(len(k_path)))
                return k_path
            alter_path.sort(key=lambda x:x[-1])
            x=alter_path[0][-1]
            y=len(alter_path[0][0])
            u=0
            for i in range(len(alter_path)):
                if alter_path[i][-1]!=x:
                    break
                if len(alter_path[i][0])<y:
                    y=len(alter_path[i][0])
                    u=i
            k_path.append(alter_path[u])
            alter_path.pop(u)
        for item in k_path:
            print(item)
        return k_path
    
    network=[[0,3,2,0,0,0],
            [3,0,1,4,0,0],
            [2,1,0,2,3,0],
            [0,4,2,0,2,1],
            [0,0,3,2,0,2],
            [0,0,0,1,2,0]]
    k_shortest_path(network,1,6,10)

    运行结果

     演示讲解

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    android_firewall or Droidwall http://code.google.com/p/droidwall/
    CMDProcessorLibrary
    Pimp_my_Z1
    HoloGraphLibrary
    程序猿正本清源式进化的意义
    UnsatisfiedLinkError: No implementation found for , AndroidStudio使用*.so
    HUNNU-10307-最优分解问题
    Spring声明式事务
    【献给CWNU的师弟】Web篇
    迪科斯彻算法总结
  • 原文地址:https://www.cnblogs.com/ljy1227476113/p/14779065.html
Copyright © 2020-2023  润新知