zoukankan      html  css  js  c++  java
  • 深度优先搜索-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()
     
  • 相关阅读:
    硝烟中的Scrum和XP-我们如何实施Scrum 12)发布计划 13)组合XP
    php array key 的存储规则
    IE下单选按钮隐藏后点击对应label无法选中的bug解决
    使用QML自绘页面导航条
    unity 获取物体尺寸
    输出众数,输出超限问题
    HTTP请求具体解释
    app 设计原则 ,步骤
    Distinct Subsequences
    OSX: 禁止iCloud钥匙链?
  • 原文地址:https://www.cnblogs.com/an-wl/p/13268344.html
Copyright © 2011-2022 走看看