• 深度优先搜索-Roads


    N个城市,编号1到N。城市间有R条单向道路。
    每条道路连接两个城市,有长度和过路费两个属性。
    Bob只有K块钱,他想从城市1走到城市N。问最短共需要走多长的路。
    如果到不了N,输出-1
    2<=N<=100
    0<=K<=10000
    1<=R<=10000
    每条路的长度 L, 1 <= L <= 100,每条路的过路费T , 0 <= T <= 100
    输入:
    K N R s1
    e1 L1 T1
    s1 e2 L2 T2
    ...
    sR eR LR TR
    s e是路起点和终点
    解题思路:从城市 1开始深度优先遍历整个图,找到所有能过到达 N 的走法,
    选一个最优的。
    最优性剪枝:
    1) 如果当前已经找到的最优路径长度为L ,那么在继续搜索的过程中,总长度已经大于
    等于L的走法,就可以直接放弃,不用走到底了
    保存中间计算结果用于最优性剪枝:
    2) 用midL[k][m] 表示:走到城市k时总过路费为m的条件下,最优路径的长度。若在
    后续的搜索中,再次走到k时,如果总路费恰好为m,且此时的路径长度已经超过
    midL[k][m],则不必再走下去了。

    输入:
    5
    6
    7
    1 2 2 3
    2 4 3 3
    3 4 2 4
    1 3 4 1
    4 6 2 1
    3 5 2 0
    5 4 3 2
    输出:
    11

    python算法实现:
      1 INF = float("inf")
      2 # k-钱,N-终点,R-共有多少条边
      3 K, N, R = 0, 0, 0
      4 # 当前找到的最优路径的长度
      5 minLen = INF
      6 # 正在走的路径的长度、正在走的路径的花销
      7 totalLen, totalCost = 0, 0
      8 # 城市是否已经走过的标记
      9 visited = []
     10 nodeList = list()
     11 # minL[i][j]表示从1到i点的,花销为j的最短路的长度
     12 minL = [[INF for cols in range(10100)] for rows in range(110)]
     13 
     14 # 存储邻接表的class结构
     15 class Node():
     16     def __init__(self, code, data=None, bnext=None):
     17         self.code = code
     18         self.data = dict()
     19         self.bnext = list()
     20 
     21 
     22 # 从s点开始向N行走
     23 def dfs(s):
     24     global K, N, minLen, totalLen, totalCost, nodeList, minL
     25     # 说明走到终点
     26     if s == N:
     27         minLen = min(minLen, totalLen)
     28         return
     29     #对s有多少条可以走出去的边进行遍历
     30     # 获取list中s与code相等的索引位置
     31     index = 0
     32     # 在nodeList列表中找s起始点的索引位置
     33     for i, item in enumerate(nodeList):
     34         if s == item.code:
     35             index = i
     36             break
     37     # 对起始点的所有的相邻点都进行遍历
     38     for i, item in enumerate(nodeList[index].bnext):
     39         # 走当前点的费用大于手里有的总金额,不能走,遍历下一条路
     40         # 也就是钱不够用了,data是字典,key-顶点,value-列表,索引0:长度,索引1:花费金额
     41         if totalCost + nodeList[index].data.get(item)[1] > K:
     42             continue
     43         # 如果该点没有访问过
     44         if visited[item] == 0:
     45             # 如果totalLen+当前点的路径长度大于之前的最优路径长度,说明不是
     46             # 最优的路径,所以之后的路不需要再递归走了
     47             if totalLen + nodeList[index].data.get(item)[0] >= minLen:
     48                 continue
     49             # 如果走到当前节点花费的价钱相同,如果路径更长的话,则不继续往下走
     50             # 第2种最优性剪枝
     51             if totalLen + nodeList[index].data.get(item)[0] > minL[item][totalCost + nodeList[index].data.get(item)[1]]:
     52                 continue
     53             minL[item][totalCost + nodeList[index].data.get(item)[1]] = totalLen + nodeList[index].data.get(item)[0]
     54             totalLen += nodeList[index].data.get(item)[0]
     55             totalCost += nodeList[index].data.get(item)[1]
     56             visited[item] = 1
     57             dfs(item)
     58             # 本条路线走完该点后,需要重新把点的标记、长度和花费都重置,
     59             # 因为下次新的路线可能还会走该点
     60             visited[item] = 0
     61             totalLen -= nodeList[index].data.get(item)[0]
     62             totalCost -= nodeList[index].data.get(item)[1]
     63     return 0
     64 
     65 
     66 def main():
     67     global K, N, R, visited, minLen, nodeList
     68     K, N, R = map(int, input().split())
     69     visited = [0 for i in range(N+1)]
     70     # 构造邻接表
     71     for i in range(R):
     72         s, t, l, c = map(int, input().split())
     73         in_flag = False
     74         tempNode = Node(s)
     75         tempNode.bnext.append(t)
     76         tempNode.data.update({t: [l, c]})
     77         if len(nodeList) > 0:
     78             for j in nodeList:
     79                 if s == j.code:
     80                     in_flag = True
     81                     break
     82             if in_flag:
     83                 j.bnext.append(t)
     84                 j.data.update({t: [l, c]})
     85             else:
     86                 nodeList.append(tempNode)
     87         else:
     88             nodeList.append(tempNode)
     89     tempNode = Node(0)
     90     tempNode.bnext.append(0)
     91     tempNode.data.update({0: [0, 0]})
     92     nodeList.insert(0, tempNode)
     93     # 因为从1号点开始,所以先把1号点标志已走过
     94     visited[1] = 1
     95     # 从1号点开始深度搜索
     96     dfs(1)
     97     # 如果minLen小于无穷大,说明找到了最优的路径,否则输出-1
     98     if minLen < float("inf"):
     99         print(minLen)
    100     else:
    101         print(-1)
    102     return 0
    103 
    104 
    105 if __name__ == '__main__':
    106     main()
     
  • 相关阅读:
    20220528 08:00:01
    208. Implement Trie (Prefix Tree) (Rust version)
    【mq】从零开始实现 mq12消息的批量发送与回执
    【mq】从零开始实现 mq08配置优化 fluent
    【mq】从零开始实现 mq13注册鉴权 auth
    【mq】从零开始实现 mq10消费者拉取消息回执 pull message ack
    【mq】从零开始实现 mq09消费者拉取消息 pull message
    【mq】从零开始实现 mq11消费者消息回执添加分组信息 pull message ack groupName
    学习随笔
    算法随笔
  • 原文地址:https://www.cnblogs.com/an-wl/p/13268344.html
Copyright © 2020-2023  润新知