IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python 最短路径之存在某种限制条件下求最小值 -> 正文阅读

[Python知识库]Python 最短路径之存在某种限制条件下求最小值

最近总结路径规划的方法,其中被Dijkstra, SPFA, 优先队列,BFS方法整蒙,有以下几点:

  • SPFA即可以用deque实现(朴素),也可以用heapq实现
  • Dijkstra即可以用deque实现(朴素),也可以用heapq实现
  • heapq实现的SPFA/Dijkstra,跟优先队列的方法有区别吗?
  • BFS不就是朴素的Dijkstra吗?
  • while循环中什么时候可以return,什么时候不能return

其中总结方法最棘手的是求存在某种限制条件下的最小值,即规定时间内达到终点的最小花费K站中转内最便宜的航班两题.前者使用SPFA求解,时间最短,而后者使用SPFA却不能通过所有案例!!! -_-

规定时间内达到终点的最小花费

# heap + Dijkstra (SPFA), 时间最快!!!
class Solution:
    def minCost(self, maxTime, edges, passingFees):
        n = len(passingFees)
        g = collections.defaultdict(list)
        for u, v, t in edges:
            g[u].append((v, t))
            g[v].append((u, t))
        times = [0] + [float('inf')] * (n - 1)
        q = [(passingFees[0], 0, 0)] # cost, time, node
        while q:
            cost, time, node = heapq.heappop(q)
            if node == n - 1: return cost
            for neighbor, t in g[node]:
                if time + t < times[neighbor] and time + t <= maxTime:
                    times[neighbor] = time + t 
                    heapq.heappush(q, (cost + passingFees[neighbor], time + t, neighbor))
        return -1

很奇怪,该代码如果使用deque实现SPFA的话,并不能完全通过(65/92)!!!
(可能是鄙人实现有误吧,代码如下,希望有大佬看到能够指导我一下)

from collections import deque
class Solution:
    def minCost(self, maxTime, edges, passingFees):
        n = len(passingFees)
        g = collections.defaultdict(list)
        for u, v, t in edges:
            g[u].append((v, t))
            g[v].append((u, t))
        times = [0] + [float('inf')] * (n - 1)
        q = deque([(passingFees[0], 0, 0)]) # cost, time, node
        res = []
        while q:
            cost, time, node = q.popleft()
            if node == n - 1:
                res.append(cost)
                continue
            for neighbor, t in g[node]:
                if neighbor not in q:
                    if time + t < times[neighbor] and time + t <= maxTime:
                        times[neighbor] = time + t
                        q.append((cost + passingFees[neighbor], time + t, neighbor))
        return -1 if not res else min(res)

K站中转内最便宜的航班

这里采用SPFA代码如下:

from collections import defaultdict
from heapq import *
class Solution(object):
    def findCheapestPrice(self, n, flights, src, dst, k):
        grids = defaultdict(list)
        for u, v, w in flights:
            grids[u].append((v, w))
        costs = [float('inf')] * n
        costs[src] = 0
        q = [(0, 0, src)]
        while q:
            c, num, cur = heappop(q)
            for nex, x in grids[cur]:
                if costs[nex] > x + c and num + 1 <= k + 1:
                    costs[nex] = x + c
                    heappush(q, (x + c, num + 1, nex))
        return -1 if costs[dst] == float('inf') else costs[dst]

该方法没有通过所有案列!!!原因在于不能if costs[nex] > x + c,因为可能达到中间某个点是较长路径,此时没有将该情况加入heap中,但最后这条路径却是最优的路径!

注意此题与上一题题的区别,一个是节点值,一个是边权值!!!所以本题不能进行if costs[nex] > x + c判断.其实这两题是相反的,一个是边权一定范围内,取最小节点值(1928);一个是节点数/边数一定范围内,取最小边权值(本题)

此题最优的方法采用的是贝尔曼-福特Bellman-Ford算法

# 贝尔曼-福特Bellman-Ford算法
# https://www.jianshu.com/p/b876fe9b2338
class Solution(object):
    def findCheapestPrice(self, n, flights, src, dst, k):
        dist = [float('inf')] * n  # dist[v]表示到达v的最小花费
        dist[src] = 0
        for i in range(k + 1):  # 对每条边做 k+1 次松弛操作,每次松弛操作实际上是对相邻节点的访问,所以总的中转为k次
            dist_old = [_ for _ in dist]
            for u, v, w in flights:
                dist[v] = min(dist[v], dist_old[u] + w)
        return dist[dst] if dist[dst] != float('inf') else -1

与该题类似的题:

有边数限制的最短路

在这里插入图片描述

n, m, k = map(int, input().split())
grids = []
for _ in range(m):
    grids.append(list(map(int, input().split())))

def bellmanFord(grids):
    dist = [float('inf')] * (n + 1)
    dist[1] = 0
    for i in range(k):
        dist_old = [_ for _ in dist]
        for u, v, w in grids:
            dist[v] = min(dist[v], dist_old[u] + w)
    return dist[n] if dist[n] != float('inf') else str('impossible')
res = bellmanFord(grids)
print(res)

Bellman-Ford算法是对边进行松弛,所以这里要求最多k条边即表示最多松弛k次。如果是最多中转k个点,则表示最多松弛k+1次。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-08-04 11:09:46  更:2021-08-04 11:10:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/12 13:55:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码