题目
【问题描述】采用深度优先搜索算法求解TSP问题,并在搜索过程中,使用界限条件(当前结点已经走过的路径长度要小于已求得的最短路径)进行“剪枝”操作(不再对后续结点进行遍历),从而提高搜索效率。采用queue模块中的栈(LifoQueue)来实现深度优先搜索。
【输入形式】在屏幕上输入顶点个数和连接顶点间的边的邻接矩阵,边上的权可能有小数点。
【输出形式】在整个算法过程中的先后搜索路径(最多输出20次最先搜索的路径),最优值和其中一条最优路径。
【样例1输入】
4
0 30 6 4
30 0 5 10
6 5 0 20
4 10 20 0
【样例1输出】
1
1->2
1->2->3
1->2->3->4
1->2->4
1->3
1->3->2
1->3->2->4
1->3->4
1->4
1->4->2
1->4->2->3
1->4->3
25: 1->3->2->4
【样例说明】
输入:顶点个数为4。连接顶点间边的邻接矩阵大小为4行4列,位置[i,j]上元素值表示第i个顶点到第j个顶点的距离,0表示两个顶点间没有边连接。
输出:在整个算法过程中的先后搜索路径,最优值为25,最优路径为:1->3->2->4。
【评分标准】根据输入得到准确的输出。
import numpy as np
import queue
class VertexNode(object):
def __init__(self, path=None, cost=0):
self.path = path
self.cost = cost
def depth_first(b, s_index, n):
best_cost = np.inf
best_path = None
m = 20
start_node = VertexNode(path=[s_index], cost=0)
open = queue.LifoQueue()
open.put(start_node)
while not open.empty():
cur_node = open.get()
if m > 0:
showpath(cur_node)
m -= 1
if cur_node.cost >= best_cost: # 剪枝
continue
# 是叶节点
if len(cur_node.path) == n:
new_cost = cur_node.cost + b[cur_node.path[-1] - 1, 0] # 当前加上回到1的费用
if new_cost < best_cost:
best_cost = new_cost
best_path = list(cur_node.path)
continue
# 不是叶节点
for i in range(n, 0, -1):
if not (i in cur_node.path):
new_cost = cur_node.cost + b[cur_node.path[-1]-1, i-1]
if new_cost < best_cost:
new_path = list(cur_node.path)
new_path.append(i)
new_node = VertexNode(path=new_path, cost=new_cost)
open.put(new_node)
return best_cost, best_path
def showpath(cur_node):
if len(cur_node.path) == 1:
print(cur_node.path[-1])
elif len(cur_node.path) > 1:
for i in range(len(cur_node.path)):
if i != len(cur_node.path)-1:
print(f"{cur_node.path[i]}->", end="")
else:
print(f"{cur_node.path[i]}")
def main():
n = int(input())
a = []
for i in range(n):
a.append(list(map(np.double, input().rstrip().split())))
b = np.array(a).reshape(n, n)
b[b == 0] = np.inf
s_index = 1
best_cost, best_path = depth_first(b, s_index, n)
if best_cost == int(best_cost):
print(f"{int(best_cost)}", end=": ")
else:
print(f"{best_cost}", end=": ")
for i in range(len(best_path)):
if i != len(best_path)-1:
print(f"{best_path[i]}->", end="")
else:
print(f"{best_path[i]}")
if __name__ == '__main__':
main()