深度优先搜索-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()

 

 
posted @ 2020-07-08 17:55  StudyNLP  阅读(199)  评论(0编辑  收藏  举报