思路参考:https://blog.csdn.net/joekwok/article/details/4749713
以旅行商问题为关键词搜索,找了一圈没有发现比较优雅的解决方法,大多是固定大小与数据,所以打算自己写一个。
这种算法思想叫做状态压缩动态回归(状压DP),感兴趣的话还可以以此为关键词搜索了解更多有关内容。本文只介绍该算法思想在旅行商问题(Travelling salesman problem,TSP)上的应用。
旅行商问题的讲解可以参考这个链接,我对其代码进行了改进,使得能针对不同的带权图,修改宏表示的城市个数N、全局变量表示的带权图距离矩阵distances[N][N]就能解决不同的TSP(旅行商问题)。本代码中distances[N][N]采用随机数生成,可根据自己需要更改。
由于内存的限制,本代码在城市个数N ≤ \le ≤ 15时运行正常;当城市个数N > > > 15时,建议将数据存入文件,通过读取文件实现。
代码的关键是用二进制01来代表城市集合,例如对于城市1,2,3组成的集合 { 1 , 2 , 3 } \{1,2,3\} { 1,2,3},用二进制 111 111 111表示,即十进制的 7 7 7,二维数组dp的第7列;对于城市1,3组成的集合 { 1 , 3 } \{1,3\} { 1,3},用二进制 101 101 101表示,即十进制的 5 5 5,二维数组dp的第5列。
所以,我们的目标是 d p [ 0 ] [ 11 1 2 ] dp[0][111_2] dp[0][1112],即 d p [ 0 ] [ 7 10 ] dp[0][7_{10}] dp[0][710],代表从 0 0 0号城市出发,将要走过城市群 { 1 , 2 , 3 } \{1,2,3\} { 1,2,3},动态规划的过程参考上面提到的链接。
下面代码的理解上,重点是看懂里面很多的对二进制数的操作,其他就不难理解了。
填表法的动态规划结果打印都是递归的方法,path[i][j]存储:从i号城市出发,将要经过j的二进制形式表示的城市群,i号城市的下一个城市的编号。
#include <iostream>
#include <cstdlib>