<OJ_Sicily>Travelling Salesman Problem

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;
}
时间: 2024-11-09 00:10:08

<OJ_Sicily>Travelling Salesman Problem的相关文章

构造 - HDU 5402 Travelling Salesman Problem

Travelling Salesman Problem Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5402 Mean: 现有一个n*m的迷宫,每一个格子都有一个非负整数,从迷宫的左上角(1,1)到迷宫的右下角(n,m),并且使得他走过的路径的整数之和最大,问最大和为多少以及他走的路径. analyse: 首先,因为每个格子都是非负整数,而且规定每个格子只能走一次,所以为了使和尽可能大,必定是走的格子数越多越好.这样我们就需

hdu5402 Travelling Salesman Problem(棋盘染色+模拟)

题目: Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 906    Accepted Submission(s): 331 Special Judge Problem Description Teacher Mai is in a maze with n rows and m c

HDOJ 5402 Travelling Salesman Problem 模拟

行数或列数为奇数就能够所有走完. 行数和列数都是偶数,能够选择空出一个(x+y)为奇数的点. 假设要空出一个(x+y)为偶数的点,则必须空出其它(x+y)为奇数的点 Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 747    Accepted Submission(s): 272

多校9 1007 Travelling Salesman Problem

Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 829    Accepted Submission(s): 182Special Judge Problem Description Teacher Mai is in a maze with n rows and m columns

【HDOJ 5402】Travelling Salesman Problem

[HDOJ 5402]Travelling Salesman Problem 一开始以为是搜索 仔细画了画发现就一模拟 奇数行或奇数列的时候怎么走都能全走完 偶数行偶数列的时候就要挑了 . * . * . * * . * . * . . * . * . * * . * . * . 以4*6为例(如上图 星号可以保证不取其中一个可遍历完全图 点好的话就会连带一些星号 所以绕过星号中的最小值 是最佳遍历方式 输入的时候找到最小值并记录下行列 遍历到改行前以 右走到头 下 左走到头 下 右走到头这种方

HDU 5402 Travelling Salesman Problem (模拟 有规律)

Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 568    Accepted Submission(s): 200 Special Judge Problem Description Teacher Mai is in a maze with n rows and m colum

HDU 5402 Travelling Salesman Problem (构造)(好题)

大致题意:n*m的非负数矩阵,从(1,1) 只能向四面走,一直走到(n,m)为终点,路径的权就是数的和,输出一条权值最大的路径方案 思路:由于这是非负数,要是有负数就是神题了,要是n,m中有一个是奇数,显然可以遍历,要是有一个偶数,可以画图发现,把图染成二分图后,(1,1)为黑色,总能有一种构造方式可以只绕过任何一个白色的点,然后再遍历其他点,而绕过黑色的点必然还要绕过两个白色点才能遍历全部点,这是画图发现的,所以找一个权值最小的白色点绕过就可以了, 题解给出了证明: 如果n,mn,m都为偶数,

PAT 甲级 1150 Travelling Salesman Problem

https://pintia.cn/problem-sets/994805342720868352/problems/1038430013544464384 The "travelling salesman problem" asks the following question: "Given a list of cities and the distances between each pair of cities, what is the shortest possib

1150 Travelling Salesman Problem (25 分)

1150 Travelling Salesman Problem (25 分) The "travelling salesman problem" asks the following question: "Given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city and retu