1.问题定义

TSP问题(旅行商问题)是指旅行家要旅行n个城市,要求各个城市经历且仅经历一次然后回到出发城市,并要求所走的路程最短。

假设现在有四个城市,0,1,2,3,他们之间的代价如图一,可以存成二维表的形式

       

图一

现在要从城市0出发,最后又回到0,期间1,2,3都必须并且只能经过一次,使代价最小。

2.动态规划可行性

设s, s1, s2, …, sp, s是从s出发的一条路径长度最短的简单回路,假设从s到下一个城市s1已经求出,则问题转化为求从s1到s的最短路径,显然s1, s2, …, sp, s一定构成一条从s1到s的最短路径,所以TSP问题是构成最优子结构性质的,用动态规划来求解也是合理的。

3.推导动态规划方程

假设从顶点s出发,令d(i, V’)表示从顶点i出发经过V’(是一个点的集合)中各个顶点一次且仅一次,最后回到出发点s的最短路径长度。

推导:(分情况来讨论)

①当V’为空集,那么d(i, V’),表示从i不经过任何点就回到s了,如上图的 城市3->城市0(0为起点城市)。此时d(i, V’)=Cis(就是 城市i 到 城市s 的距离)、

②如果V’不为空,那么就是对子问题的最优求解。你必须在V’这个城市集合中,尝试每一个,并求出最优解。

d(i, V’)=min{Cik +  d(k, V’-{k})}

注:Cik表示你选择的城市和城市i的距离,d(k, V’-{k})是一个子问题。

综上所述,TSP问题的动态规划方程就出来了:

4.实例分析

现在对问题定义中的例子来说明TSP的求解过程。(假设出发城市是 0城市)

①我们要求的最终结果是d(0,{1,2,3}),它表示,从城市0开始,经过{1,2,3}之中的城市并且只有一次,求出最短路径.

②d(0,{1,2,3})是不能一下子求出来的,那么他的值是怎么得出的呢?看上图的第二层,第二层表明了d(0,{1,2,3})所需依赖的值。那么得出:

d(0,{1,2,3})=min  {

C01+d(1,{2,3})

C02+d{2,{1,3}}

C03+d{3,{1,2}}

}

③d(1,{2,3}),d(2,{1,3}),d(3,{1,2})同样也不是一步就能求出来的,它们的解一样需要有依赖,就比如说d(1,{2,3})

d(1,{2,3})=min{

C12+d(2,{3})

C13+d(3,{2})

}

d(2,{1,3}),d(3,{1,2})同样需要这么求。

④按照上面的思路,只有最后一层的,当当V’为空集时,Cis的值才可以求,它的值是直接从

这张表里求得的。

5.编程思路

将d(i, V’)转换成二维表,d[i][j]

在程序中模拟填表的过程,主要要考虑到j这个参数的表示,它要代表一个集合,可以用二维数组来表示。

6.源代码

实现上略有不同,d[i][k] 表示从i出发经过k中所有标志位为1的点(这里面是包括i的)后到达终点。

#include <iostream>
#include <memory.h>
#include <climits>
#include <algorithm> using namespace std; #define MAX_CITY_NUM 10 // the number of the cities
int n;
// the city map
int cityMap[MAX_CITY_NUM][MAX_CITY_NUM]; //if city number less than 32, can use this simple method.(in vs2013, more than 25 will cause an "array is too large" error)
int tsp1()
{
int ret = INT_MAX;
int d[MAX_CITY_NUM][ << MAX_CITY_NUM]; //current city and past city for (int i = ; i < MAX_CITY_NUM; i++)
for (int j = ; j < << MAX_CITY_NUM; j++)
d[i][j] = INT_MAX; //init every city to city0
for (int i = ; i < n; i++)
{
d[i][<<i] = cityMap[i][];
} for (int i = n-; i >= ; i--) // the start city.
for (int j = ; j < n; j++) //the end city.
for (int k = ; k < << n; k++)
{
if (d[j][k&~( << i)] != INT_MAX && (k >> j & ) && (k >> i & ))
{
//cout << d[i][k] << endl;
//cout << d[j][k&~(1 << i)] + cityMap[i][j] << endl;
d[i][k] = min(d[i][k], d[j][k&~( << i)] + cityMap[i][j]);
//if (d[i][k] < INT_MAX)
//cout << "d[" << i << "][" << k << "] = " << d[i][k] << endl;
} } ret = d[][( << n) - ]; return ret;
} int main()
{
//init data.
n = ;
memset(cityMap, , sizeof(cityMap));
cityMap[][] = ;
cityMap[][] = ;
cityMap[][] = ;
cityMap[][] = ;
cityMap[][] = ;
cityMap[][] = ;
cityMap[][] = ;
cityMap[][] = ;
cityMap[][] = ;
cityMap[][] = ;
cityMap[][] = ;
cityMap[][] = ; cout << tsp1() << endl;
}

TSP(旅行者问题)——动态规划详解(转)的更多相关文章

  1. leetcode-53-Maximum Subarray(动态规划详解)

    题目描述: Given an integer array nums, find the contiguous subarray (containing at least one number) whi ...

  2. (转)dp动态规划分类详解

    dp动态规划分类详解 转自:http://blog.csdn.NET/cc_again/article/details/25866971 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间 ...

  3. HDU 1024 Max Sum Plus Plus【动态规划求最大M子段和详解 】

    Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  4. 详解动态规划(Dynamic Programming)& 背包问题

    详解动态规划(Dynamic Programming)& 背包问题 引入 有序号为1~n这n项工作,每项工作在Si时间开始,在Ti时间结束.对于每项工作都可以选择参加与否.如果选择了参与,那么 ...

  5. 动态规划晋级——HDU 3555 Bomb【数位DP详解】

    转载请注明出处:http://blog.csdn.net/a1dark 分析:初学数位DP完全搞不懂.很多时候都是自己花大量时间去找规律.记得上次网络赛有道数位DP.硬是找规律给A了.那时候完全不知数 ...

  6. iOS socket原理及连接过程详解

    连接过程图解(度娘的拿过来用)

  7. Iptables详解七层过滤

    <Iptables详解七层过滤> 一.防火墙简介 防火墙其实就是一个加固主机或网络安全的一个设备或者软件而已,通过防火墙可以隔离风险区域与安全区域的连接,同时不会妨碍风险区域的访问.当然需 ...

  8. 基于双向BiLstm神经网络的中文分词详解及源码

    基于双向BiLstm神经网络的中文分词详解及源码 基于双向BiLstm神经网络的中文分词详解及源码 1 标注序列 2 训练网络 3 Viterbi算法求解最优路径 4 keras代码讲解 最后 源代码 ...

  9. 【最短路径Floyd算法详解推导过程】看完这篇,你还能不懂Floyd算法?还不会?

    简介 Floyd-Warshall算法(Floyd-Warshall algorithm),是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法名称以 ...

随机推荐

  1. css透明度的设置 (兼容所有浏览器)

    一句话搞定透明背景! .transparent_class { filter:alpha(opacity=); -moz-opacity:0.5; -khtml-opacity: 0.5; opaci ...

  2. leetcode 100 Same Tree ----- java

    Given two binary trees, write a function to check if they are equal or not. Two binary trees are con ...

  3. 数据库实验一 SQL Service的安装

    SQL 2014 安装需要 Microsoft .Net Framework 3.5框架 win 8.1 Microsoft .Net Framework 3.5框架安装教程:点我 安装图文教程:点我 ...

  4. 固定虚拟机的IP

  5. php MySQL数据库操作类源代码

    php MySQL数据库操作类源代码: <?php class MySQL{ private $host; //服务器地址 private $name; //登录账号 private $pwd; ...

  6. Awesome Python

    Awesome Python  A curated list of awesome Python frameworks, libraries, software and resources. Insp ...

  7. Google Java Style Guide

    https://google.github.io/styleguide/javaguide.html   Table of Contents 1 Introduction 1.1 Terminolog ...

  8. ogistic regression (逻辑回归) 概述

    :http://hi.baidu.com/hehehehello/blog/item/0b59cd803bf15ece9023d96e.html#send http://en.wikipedia.or ...

  9. centos6.7 本地yum源配置

    [BEGIN] 2016/11/9 21:47:31[root@11g ~]# mount /dev/cdrom /mediamount: block device /dev/sr0 is write ...

  10. #你好Unity3D#Project脚本执行双击资源操作

    Unity的Project里面放了很多游戏资源,比如脚本或者图片.正常情况下我们可以通过鼠标双击来进行打开.假如我现在不想主动双击打开,我想自动打开某个脚本或者图片再或者别的资源怎么办? 如下代码所示 ...