TSP问题——动态规划

            Traveling Salesman Problem

  Description:                    Time Limit: 4sec    Memory Limit:256MB

  有编号1到N的N个城市,问从1号城市出发,遍历完所有的城市并最后停留在N号城市的最短路径长度。

  Input:

  第一行整数 T :T组数据 (T<=20) 

  每个case 读入一个N( 2 <= N <= 20),接着输入N行,第i行有两个整数 xi , yi 表示第 i 个城市坐标轴上的坐标 。

  Output:

  每个case输出一个浮点数表示最短路径。四舍五入保留两位小数。

  Sample Input:

  1 4 0 0 1 0 1 1 0 1

  Sample Output:

  3.41

  经典难题!数据开到这么小就知道没有那么简单的复杂度了,一般的算法,即爆搜,复杂度为 o( n! ) ,我们这里采用的动态规划算法,

  算法复杂度已经从阶乘级降到了o( ( n^2 )*( 2^n ) ) (看起来也是相当恐怖的,不过像这种经典难题这种复杂度对我来说已经不错了)。

  开始说说思路,一开始马上想到的必然是搜索,搜索必然超时,于是某大神直接告诉我——记忆化搜索,记忆化搜索能做的动规就能做,写递归太麻烦了于是动规!

  题目中起点终点确定,于是我们可以用一个二维dp数组来保存一个状态——dp[i]{V}表示从结点0到结点 i 途经V中所有节点的最短路径长(这里的V是一个集合)

  于是状态转移方程可以为:dp[i]{V}=min( dp[i]{V} , dist[i][j]+dp[j]{V-{j}} )  (j 属于 V)

  好的大思路定好了,我们来考虑细节部分,主要有以下部分:

  1)建图等等:结构体point,距离函数dist;

  2)集合V的表示:二进制数,即010表示三个数的集合第二个有,其余无;

  3)dp过程的范围:1 ~ n-1 (最大可能为 1 ~ 18 );

  

  于是我们可以敲代码啦!

#include <bits/stdc++.h>
const double INF=10e7;

using namespace std;

int T,n,cnt;
double a[25][25],dp[25][1100000];

struct point{		//结点结构体
	int x,y;
}pt[25];

double d(point a,point b){		//结点间距离
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

int main()
{
	scanf("%d",&T);
	while(T--)
	{
		cnt=1;
		scanf("%d",&n);
		for(int i=2;i<n;i++) cnt<<=1;		//组合数(除起点终点外) 

		for(int i=0;i<n;i++)				//输入
			scanf("%d %d",&pt[i].x,&pt[i].y);

		for(int i=0;i<n;i++)				//建边
			for(int j=0;j<n;j++)
				a[i][j]=d(pt[i],pt[j]);

		for(int i=0;i<n;i++)				//初始化
			for(int j=0;j<cnt;j++)
				dp[i][j]=INF;

		for(int i=0;i<n;i++)				//起点确定,定下初始条件
			dp[i][0]=a[i][0];
		for(int i=1;i<cnt;i++)				//从有元素考虑起
			for(int j=1;j<n-1;j++)
			{
				for(int k=1;k<n-1;k++)
				{
					if((1<<k-1)&i)		//k is in the set
						dp[j][i]=min(dp[j][i],a[j][k]+dp[k][i-(1<<k-1)]);	//状态转移方程
				}
			}
		double ans=INF;
		for(int i=1;i<n;i++)
			ans=min(ans,dp[i][cnt-1]+a[i][n-1]);

		printf("%.2lf\n",ans);
	}

	return 0;
}

  之前动态规划也是做了不少的基础例题,这道题算是动态规划的第一次成功应用,还是蛮开心的,软创得加油啊!

  

时间: 2024-10-02 02:09:12

TSP问题——动态规划的相关文章

uva 116 Unidirectional TSP(动态规划,多段图上的最短路)

这道题目并不是很难理解,题目大意就是求从第一列到最后一列的一个字典序最小的最短路,要求不仅输出最短路长度,还要输出字典序最小的路径. 这道题可以利用动态规划求解.状态定义为: cost[i][j] = max{cost[i+1][j+k]+c[i][j]}(k=-1,0,1) 关于最短路长度的求法,我们可以通过上边的状态转移方程递推求解.cost代表从第i列到第c-1列的最短路,只要找出cost[0][j](j代表行号)中的最大值,我们得到的结果就是最短路. 我们已经得到了最短路的长度.下一步,

TSP问题[动态规划]

分析: 有用的量:城市集合V={a,b,c,d,--} 所以我们用 T(i,V) 表示从 城市 i 出发遍历集合 V 中的城市一遍且仅一遍后回到 i 所用的最少费用(这里可能表达不好,底下会看到,但是于代码方面无碍) 用T(k,{空集合})表示从最后一个点 k 回到起点 i 的费用 所以:

旅行商问题(TSP)之动态规划解法

http://soj.sysu.edu.cn/show_problem.php?pid=1000&cid=1769 sicily Traveling Salesman Problem 有编号1到N的N个城市,问从1号城市出发,遍历完所有的城市并最后停留在N号城市的最短路径长度. Input 第一行整数 T :T组数据 (T<=20) 每个case 读入一个N( 2 <= N <= 20),接着输入N行,第i行有两个整数 xi,yi表示 第i个城市坐标轴上的坐标,两个城市的距离定义

uva 116 - Unidirectional TSP (动态规划)

第一次做动规题目,以下均为个人理解以及个人方法,状态转移方程以及状态的定义也是根据个人理解,请过路大神指教. 状态:每一列的每一个数[ i ][ j ]都是一个状态: 然后定义状态[ i ][ j ]的指标函数d[ i ][ j ]为从[ i ][ j ]向右出发的可以得到的最小的整数和: 状态转移方程:d[ i ][ j ]=min(d[ i+1 ][ j+1 ][ i-1 ][ j+1 ][ i ][ j+1 ])+a[ i ][ j ]; 其中a[ i ][ j ]为当前位置的数值: 然后

动态规划经典问题--TSP问题

Travelling Salesman Problem 旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市.路径的选择目标是要求得的路径路程为所有路径之中的最小值. 旅行商问题是图论中最著名的问题之一,即"已给一个n个点的完全图,每条边都有一个长度,求总长度最短的经过每个顶点正好一次的封

多线程动态规划算法求解TSP(Traveling Salesman Problem) 并附C语言实现例程

TSP问题描述: 旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市.路径的选择目标是要求得的路径路程为所有路径之中的最小值.这篇文章解决的tsp问题的输入描述是: TSP问题的动态规划解法: 引用一下这篇文章,觉得作者把动态规划算法讲的非常明白:https://blog.csdn.ne

【UVA116】 单向TSP Unidirectional TSP [动态规划]

一遍dp 要注意转移时它行号注意判断 因为它行是一个环 然后就是UVa一如既往令人窒息的输入输出 主要按的刘汝佳的思路 1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 #include<cmath> 6 #include<stack> 7 #include<algorithm> 8 using namespace

poj3311 经典tsp问题

题目的大概意思就是一个人到一些城市送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一个城市可重复访问多次. 由于题中明确说了两个城市间的直接可达路径(即不经过其它城市结点)不一定是最短路径,所以需要借助邻接矩阵首先求出任意两个城市间的最短距离.这一步骤使用Floyd最短路径算法即可.然后,在此基础上来求出遍历各个城市后回到出发点的最短路径的距离,即求解TSP问题. TSP问题目前有多种解法:搜索解法,动归解法,启发式解法.这里就针对poj

遗传算法解决TSP问题

1实验环境 实验环境:CPU [email protected],内存6G,windows7 64位操作系统 实现语言:java (JDK1.8) 实验数据:TSPLIB,TSP采样实例库中的att48数据源 数据地址:http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/tsp/att48.tsp.gz TSPLIB是一个从各种来源和各种类型中产生的TSP及其相关问题的采样实例库,这里选取TSP采样实例库中的att48数据源,最优值为106