无向简单图的TSP算法

小规模精确解:

算法思想:

小规模精确解的算法中心思想是动态规划思想。

假设给定顶点集合V为{0,1,2,3,4,... .n}。由于图为无向完全图,我们可以很自然地将0视为输出的起点和终点。对于每个其他顶点i(除0之外),我们找到以0为起点,i为终点,且所有顶点恰好出现一次的最小成本路径。假设定义这条最小成本路径的成本为Cost(i),则相应TSP回路的Cost将是Cost(i)+ dist(i,0)其中dist(i,0)是从i到0的距离。最后,我们返回所有[cost(i)+ dist(i,0)]值,再从中选择最小值,此时该最小值也就是TSP的最优路径。而如何获得Cost(i)呢?那就是用动态规划算法来完成了:

定义CSi):

从集合S中访问每个顶点一次,且从0开始到i结束的最小成本路径的Cost

定义动态规划递归关系:

If size of S is 2, then S must be {0, i},C(S, i) = dist(1, i)
Else if size of S is greater than 2.C(S, i) = min { C(S-{i}, j) + dis(j, i)} where j belongs to S, j != i and j != 0.

所以,根据以上定义,求解TSP最优路径,等价于求解:

min {C(S, i) + dist(i, 0)} for any i in |V – 0|

伪代码构造:

TSP(V, G)
// input: V is the vertex set, exactly i indicates ith vertex
// input: G is a matrix, which G[i][j] indicates the distance from ith node to jth one
// output: the best optimal path of TSP
// output: the total cost of the path// define C a matrix// C[i][S]: C(S, i) be the cost of the minimum cost path visiting each vertex //           in set S exactly once, starting at 1 and ending at iC(|V|, (2^|V|, -1))// define path a matrix which the value records the last node of the current nodepaths(|V|, 2^|V|)min = INT_MAXfor e in V-{0} docost = dp_TSP(G, V, C, S, e, paths) + G[e][0]if cost < min domin = costindex = eendifendforpath = []S = [all node in V]dopush index in pathtemp = indexindex = path[index][S]pop temp from Swhile index != -1push 0 in pathreturn path.reverse, mindp_TSP(G, V, C, S, i, paths)
// input: G is a matrix, which G[i][j] indicates the distance from ith node to jth one
// input: V is verties set
// input: C means C(S, i)
// input: S includes all nodes needed to visited once and only once
// input: i, which indicate the end vertex in S
// input: records the last node of the current node in C(S, i)
// output: the value of C(S, i)if |S| == 2return G[0][i]endifif C(S, i) != -1return C(S, i)endifmin = INT_MAXfor j in Sif j != {0} and j != e thenvalue = C(S-{i}, j) + G[j][i]if value <= min thenmin = valueindex = jendifendifendforC(S, i) = minpath(S, i) = indexreturn min

函数设计:

邻接矩阵读取函数设计:

TSP函数设计:

dp_TSP函数设计:

测试结果:

算法分析:

由于我们使用动态编程解决了这个问题,且动态编程方法包含子问题,子问题如下图显示:

如果我们求解递归方程,我们将得到总 个子问题,也就是。每个子问题将花费O(n)时间(找到剩余(n-1)个节点的路径)。因此总时间复杂度为。空间复杂度也是子问题的数量,即

虽然时间复杂度远小于O(n!),但仍然呈指数级。所需空间也是指数级的。因此,即使对于稍高数量的顶点,这种方法也是不可行的。由于在算法实现当中,用了long long int来作为S集合,所以超过64个节点的图就无法适用了。只能通过大规模近似求解。

完整代码:

#include <vector>
#include <iostream>using namespace std;
typedef vector<vector<int> > G;
typedef vector<int> V;
G load_graph(int n);
void TSP(G& g, int n);
int dp_TSP(G& g, G& C, long long int S, int i, G& path);
V get_set(long long int S, int n);
int main(){int n;cin>> n;G g = load_graph(n);TSP(g, n);return 0;
}G load_graph(int n){G g(n, V(n));for(int a=0; a<n; a++)for(int b=0; b<n; b++)scanf("%d", &g[a][b]);return g;
}
void printG(G& g){int n = g.size();int m = g[0].size();for(int a=0; a<n; a++){for(int b=0; b<m; b++)cout<< g[a][b]<< ' ';cout<< endl;}
}
void printV(V g){int n = g.size();for(int a=0; a<n; a++)cout<< g[a]<< ' ';cout<< endl;
}void TSP(G& g, int n){// there are (2^n - 1) probable S for each i in C(S, i)int m = (1<<n);// define a term C(S, i) be the cost of the minimum cost path visiting each vertex // in set S exactly once, starting at 1 and ending at i.G C(n, V(m, -1));// record the pathG path(n, V(m, -1));// run the dynamic programming TSP algorithm// start at 0th node, and end at 0th node// find the minimum cost path with 1 as the starting point, i as the ending pointint min = INT_MAX;int target = -1;for(int i=1; i<n; i++){// define S as a long long int variable, each ith bit record the existance of the ith node// initial S = 1<<n - 1, which means that S includes all node at firstlong long int S = (1<<n) - 1;// the cost of corresponding Cycle would be cost(i) + dist(i, 0)int cost = dp_TSP(g, C, S, i, path) + g[i][0];// the minimum of all [cost(i) + dist(i, 0)] valuesif(cost < min){min = cost;target = i;}}V output;long long int S = (1<<n) - 1;do{output.push_back(target);int temp = target;target = path[target][S];S = S^(1<<temp);}while(target != -1);//printG(C);cout<< min<< endl;for(int a=n-1; a>=0; a--)cout<< output[a]<< ' ';cout<< 0<< endl;
}int dp_TSP(G& g, G& C, long long int S, int i, G& path){V set = get_set(S, g.size());/*If size of S is 2, then S must be {0, i},C(S, i) = dist(1, i) Else if size of S is greater than 2.C(S, i) = min { C(S-{i}, j) + dis(j, i)} where j belongs to S, j != i and j != 0.*/if(set.size()==2){path[i][S] = 0;return g[0][i];}if(C[i][S] != -1)return C[i][S];int min = INT_MAX, index = -1;long long int new_S = S^(1<<i);for(int a=0; a<set.size(); a++){int j = set[a];if(j!=i && j!=0){int result = dp_TSP(g, C, new_S, j, path) + g[j][i];//cout<< i<< ' '<< result<< ' '<< j<< endl;if(result < min){min = result;index = j;}}}C[i][S] = min;path[i][S] = index;//cout<< i<< ' '<< index<< "dad"<< endl;return min;
}V get_set(long long int S, int n){V set;for(int a=0; a<n; a++)if(S & (1<<a))set.push_back(a);return set;
}

Solve TSP with dynamic programming——动态规划解决旅行商(邮递员)问题相关推荐

  1. 模拟退火(SA, Simulated Annealing)算法解决旅行商TSP问题

    01 什么是旅行商问题(TSP)? TSP问题(Traveling Salesman Problem,旅行商问题),由威廉哈密顿爵士和英国数学家克克曼T.P.Kirkman于19世纪初提出.问题描述如 ...

  2. 分支限界解决旅行商tsp问题

    本人的算法大作业 参考博客: http://blog.csdn.net/qq_32400847/article/details/51813606 http://www.cnblogs.com/ciel ...

  3. Dynamic Programming (动态规划问题)

    动态规划定义: 我们在运用分治原理解决问题时,会将问题分成好几个子问题进行递归地求解:然而存在这样一个问题:如果子问题并非相互独立的,运用分治原理将重复地计算公共的子问题,浪费许多时间. 在解决一类特 ...

  4. 遗传算法解决旅行商(TSP)问题

    遗传算法解决旅行商问题 作为NP难的经典问题,旅行商问题有多种算法可以解决. 我学习的过程中,首先看到了模拟退火算法解决旅行商问题的过程,模拟退火算法可以保证100%的找到全局最小值. 在我研究遗传算 ...

  5. 动态规划(Dynamic Programming)与贪心算法(Greedy Algorithm)

    文章目录 动态规划算法(Dynamic Programming) 动态规划问题的属性 应用实例:最长公共子序列问题(Longest Common Subsequence, LCS) 贪心算法(Gree ...

  6. 数据结构与算法(C++)– 动态规划(Dynamic Programming)

    动态规划(Dynamic Programming) 理解动态规划的好文:https://www.sohu.com/a/153858619_466939 1.基础 **定义:**递归算法经常会有一些重复 ...

  7. ADPRL - 近似动态规划和强化学习 - Note 7 - Approximate Dynamic Programming

    Note 7 - 近似动态规划 Approximate Dynamic Programming 7. 近似动态规划 (Approximate Dynamic Programming) 7.1 近似架构 ...

  8. 强化学习(二)- 动态规划(Dynamic Programming)

    3.动态规划 3.1 介绍 术语动态规划(DP:Dynamic Programming) 指的是一个算法集合,可以用来计算最优策略,给定一个完美的环境模型,作为马尔可夫决策过程(MDP).经典的DP算 ...

  9. 动态规划(Dynamic Programming)例题步骤详解

    文章目录 动态规划(Dynamic Programming)浅学 - 学习笔记 题目特点: 1.选择硬币组合问题:(Coin Change) 动态规划题四个核心步骤: 一.确定状态 二.转移方程 三. ...

最新文章

  1. CM: Create BAdI implementation for Webservice enabled word document
  2. SpringMVC的运行原理
  3. 配置Ubuntu Server高速apt-get源
  4. 计算机英语四六级对调剂有影响吗,你知道四六级对于考研的影响程度吗?
  5. 交叉编译 for arm-linux-gcc... no,QT4.8.6、tslib库移植到arm上配置出错!求大神指点
  6. python 邮件中生成图表_60秒一口Python:147个demo,助你从新手小白步步进阶编程高手...
  7. LeetCode(938)——二叉搜索树的范围和(JavaScript)
  8. 12.企业安全建设指南(金融行业安全架构与技术实践) --- 移动应用安全
  9. java 26进制转10进制_求将任意10进制数字转为26进制字母的算法
  10. (转)以案说法 | ICO,刑事风险要远离!
  11. nsis升级包_NSIS制作软件升级安装包 - 卡饭网
  12. 电脑桌面便签小工具下载,好用的桌面便签软件推荐
  13. linux 查看隐藏文件大小,Linux运维知识之linux下显示隐藏目录或隐藏文件占用空间大小...
  14. Java输出书名,输入书名 输出该书的信息 中java程序怎么设计
  15. python 微信发送图片失败什么原因_微信发不出去图片的4种解决方法
  16. Ada2012即将完成
  17. darknet训练时Couldn‘t open file的问题解决
  18. PA 调试心得(一个电容引发的问题)
  19. 工作站是高档的微型计算机 (,家用pc机和工作站有什么不同?
  20. velocity模板引擎帮助

热门文章

  1. windows内核开发学习笔记十八:IRP 处理的标准模式
  2. Python 优雅地利用两点经纬度计算地理空间距离
  3. java 蓝牙打印_Android - 将收据打印到蓝牙打印机
  4. 【Alpha阶段】第四次scrum meeting
  5. 从晶体管开始聊聊计算机为什么采用二进制
  6. 【Java】 org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor
  7. python判别性别的代码_学习文章—(Python实践)Python实现手机号自动判断男女性别...
  8. miui系统android os,color os对比miui 一加手机刷Color OS与MIUI系统体验对比评测
  9. Javascript小练习——班级学号点名器
  10. 《零基础入门学习Python》第031讲:永久存储:腌制一缸美味的泡菜