旅行推销员问题(
英语:Travelling salesman problem, TSP)是这样一个问题:给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。它是组合优化中的一个NP困难问题,在运筹学和理论计算机科学中非常重要。
分支限界法在上一篇Blog中我有简单说明,并给出了基于分支界限法的Dijkstra ,这篇文章里介绍一下基于分支限界法的TSP算法。
对于TSP,我们需要利用上界和下界来对BFS进行剪枝,通过不断更新上界和下界,尽可能的排除不符合需求的child,以实现剪枝。最终,当上限和下限等同时,我们可以获得最优的BFS解,以解决TSP问题。
在第一篇中,我们用dfs获取上界,用每行矩阵最小值来获取下界。
代码如下,下面代码中,我采用贪心法(使用DFS暴力搜索到一个结果)来获取最初的上界,通过累加每行旅行商矩阵中的最小值来获取一个下界。
//分支限界法 #include<iostream> #include<algorithm> #include<cstdio> #include<queue> const int INF = 100000; const int MAX_N = 22; using namespace std; //n*n的一个矩阵 int n; int cost[MAX_N][MAX_N];//最少3个点,最多MAX_N个点 struct Node { bool visited[MAX_N];//标记哪些点走了 int s;//第一个点 int s_p;//第一个点的邻接点 int e;//最后一个点 int e_p;//最后一个点的邻接点 int k;//走过的点数 int sumv;//经过路径的距离 int lb;//目标函数的值(目标结果) bool operator <(const Node &p)const { return p.lb < lb;//目标函数值小的先出队列 } }; priority_queue<Node> pq;//创建一个优先队列 int low, up;//下界和上界 bool dfs_visited[MAX_N];//在dfs过程中搜索过 //确定上界,利用dfs(属于贪心算法),贪心法的结果是一个大于实际值的估测结果