标签:
Description
有编号1到N的N个城市,问从1号城市出发,遍历完所有的城市并最后停留在N号城市的最短路径长度。
Input
第一行整数 T :T组数据 (T<=20)
每个case 读入一个N( 2 <= N <= 20),接着输入N行,第i行有两个整数 xi,yi表示
第i个城市坐标轴上的坐标,两个城市的距离定义为欧氏距离。
Output
每个case输出一个浮点数表示最短路径。四舍五入保留两位小数。
解题思路:使用动态规划解决旅行商问题
这道题中规定了起始点和终止点,目的是要求出从起始点到终止点,使得遍历全部城市并且路径最短。假设DP[i]{V}表示以点i作为终点,经过V集合中所有点的路径最小。
举个例子,V={2,3,4},则DP[5]{V}则表示以点5为终点,要经过点2,3,4的路径最短距离,假设这样条件下的最短距离走法是3→4→2→5,则d34 + d42 + d25 = D[5]{V}
其中dij表示从点i到点j的欧式距离。
按照这样子想的话,假设输入N个城市,则需要对N-2进行全部的排列组合得到集合V可能出现的总数comPathNum。为了方便,我们使用01表示集合,例如000111表示点第1,2,3个点不在集合中,第4,5,6个点在集合中。因此我们能够用1个数来表示一种集合情况。
状态方程为:DP[i]{V} = min( DP[i]{V}, DP[k]{V-i} + distance[i][k] ) 也就是以i为终点经过V的最短路径 =min( 原来的路径, 以k为终点经过V-i 的最短路径 + k和i直接的路径 )
获得最终的结果要加上与题目要求的终点
#include <iostream> #include <algorithm> #include <iomanip> #include <math.h> #define MAX 10e7 using namespace std; int caseNum, comPathNum, cityNum; double DP[25][1100000]; // 记录存储状态 double distanceArr[25][25]; //记录城市之间的欧式距离 struct point{ int x,y; }city[25]; double getDistance(const point &a,const point &b){ // 求两个城市之间的欧式距离 return sqrt(( a.x - b.x )*( a.x - b.x ) + (a.y - b.y)*(a.y - b.y)); } int main(int argc, const char * argv[]) { // insert code here... cin >> caseNum; while (caseNum--) { cin >> cityNum; comPathNum = 1; for (int i = 0; i < cityNum; i++) { cin >> city[i].x >> city[i].y; } for (int i = 0; i < cityNum; i++) { for (int j = 0; j < cityNum; j++) { distanceArr[i][j] = distanceArr[j][i] = getDistance(city[i], city[j]); } } comPathNum <<= (cityNum-1); for (int i = 0; i < cityNum; i++) { // 初始化状态矩阵 for (int j = 0; j < comPathNum; j++) { DP[i][j] = MAX; } } for(int i = 0; i < cityNum; i++){ // 初始化DP的第0列数 DP[i][0] = distanceArr[i][0]; } for (int i = 1; i < comPathNum; i ++) { for (int j = 1; j < cityNum; j++) { for (int k = 1; k < cityNum; k ++) { if (1<<(k-1) & i) { DP[j][i] = min(DP[j][i], distanceArr[j][k] + DP[k][i-(1<<(k-1))]); } } } } double result = MAX; for (int i = 1; i <cityNum; i++) { // 最终结果加上终点 result = min(result, DP[i][comPathNum-1] + distanceArr[i][cityNum-1]); } cout << setprecision(2)<< setiosflags(ios::fixed)<< result << endl; } return 0; }
<OJ_Sicily>Travelling Salesman Problem
标签:
原文地址:http://blog.csdn.net/vipin_pei/article/details/51353307