Algorithm, Data structure/Popular Algorithms

Travelling salesman problem

JaykayChoi 2016. 6. 5. 17:09

The travelling salesman problem (TSP) 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 exactly once and returns to the origin city?It is an NP-hard problem in combinatorial optimization, important in operations research and theoretical computer science.

Solution of a travelling salesman problem

TSP is a special case of the travelling purchaser problem and the vehicle routing problem.

In the theory of computational complexity, the decision version of the TSP (where, given a length L, the task is to decide whether the graph has any tour shorter than L) belongs to the class ofNP-complete problems. Thus, it is possible that the worst-case running time for any algorithm for the TSP increases superpolynomially (perhaps, specifically, exponentially) with the number of cities.

The problem was first formulated in 1930 and is one of the most intensively studied problems in optimization. It is used as a benchmark for many optimization methods. Even though the problem is computationally difficult, a large number of heuristics and exact algorithms are known, so that some instances with tens of thousands of cities can be solved completely and even problems with millions of cities can be approximated within a small fraction of 1%.[1]

The TSP has several applications even in its purest formulation, such as planninglogistics, and the manufacture of microchips. Slightly modified, it appears as a sub-problem in many areas, such as DNA sequencing. In these applications, the concept city represents, for example, customers, soldering points, or DNA fragments, and the concept distance represents travelling times or cost, or a similarity measure between DNA fragments. The TSP also appears in astronomy, as astronomers observing many sources will want to minimise the time spent moving the telescope between the sources. In many applications, additional constraints such as limited resources or time windows may be imposed.


출처: https://en.wikipedia.org/wiki/Travelling_salesman_problem



다양한 풀이법이 존재하는 여행하는 외판원 문제입니다. 우선 완전 탐색 방법과 동적 계획법으로 풀어보겠습니다. heuristics 이나 integer programing 방법은 아직 제가 이해하기에는 어려운 면이 있어 나중에 업데이트를 해야되겠습니다.


우선 완전 탐색 방법은 설명할 것도 없이 재귀함수를 통해 모든 경로를 탐색하여 최소값을 구하는 방법입니다.


동적 계획법은 memoization 을 통해 이미 값을 구한 경로는 반복해서 값을 구하지 않고 건너뛰는 방법입니다. 이미 들린 도시의 값을 전달하기 위해 bit mask 방법을 사용해 memoization 이 가능하도록 하였습니다.



c++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;
 
 
const int MAX_CITY = 20;
 
int numCity;
double distances[MAX_CITY][MAX_CITY];
 
#pragma region dynamic programming
double cache[MAX_CITY][<< MAX_CITY];
#pragma endregion
 
#pragma region bruteForce
double bruteForce(vector<int>& visitedCity, vector<bool>& isVisited, double curLength)
{
    if (visitedCity.size() == numCity)
        return curLength + distances[visitedCity.back()][visitedCity[0]];
 
    double ret = 987654321;
 
    for (int next = 0; next < numCity; next++)
    {
        if (isVisited[next])
            continue;
        
        int here = visitedCity.back();
        visitedCity.push_back(next);
        isVisited[next] = true;
 
        double length = bruteForce(visitedCity, isVisited, curLength + distances[here][next]);
        ret = min(ret, length);
 
        isVisited[next] = false;
        visitedCity.pop_back();
    }
 
    return ret;
}
#pragma endregion
 
 
#pragma region dynamic programming
double dynamicProgramming(int here, int visitedCity)
{
    if (visitedCity == (<< numCity) - 1)
        return distances[here][0];
 
    double& ret = cache[here][visitedCity];
 
    if (ret >= 0)
        return ret;
 
    ret = 987654321;
 
    for (int next = 0; next < numCity; next++)
    {
        if (visitedCity & (<< next))
            continue;
 
        double length = dynamicProgramming(next, visitedCity + (<< next)) + distances[here][next];
 
        ret = min(ret, length);
    }
 
    return ret;
}
#pragma endregion
 
int main() 
{
    //10 cities
    ifstream fin("input.in");
 
    fin >> numCity;
 
    memset(distances, 0sizeof(distances));
 
    for (int i = 0; i < numCity; i++)
    {
        for (int j = i + 1; j < numCity; j++)
        {
            
            double dist1;
            fin >> dist1;
            distances[i][j] = distances[j][i] = dist1;
        }
    }
    
#pragma region bruteForce
    vector<int> visitedCity;
    visitedCity.push_back(0);
    vector<bool> isVisited(numCity, false);
    isVisited[0= true;
 
    clock_t start = clock();
    cout << "bruteForce : " <<  bruteForce(visitedCity, isVisited, 0);
 
    clock_t end = clock();
    double time = double(end - start) / CLOCKS_PER_SEC;
    cout << " elapse time(s): " << time << endl;
#pragma endregion
 
 
#pragma region dynamic programming
    memset(cache, -1sizeof(cache));
 
    start = clock();
    cout << "dynamicProgramming : " << dynamicProgramming(00);
 
    end = clock();
    time = double(end - start) / CLOCKS_PER_SEC;
    cout << " elapse time(s): " << time << endl;
#pragma endregion
 
    system("pause");
    return 0;
}
cs


bruteForce : 108 elapse time(s): 13.941

dynamicProgramming : 108 elapse time(s): 0.005






'Algorithm, Data structure > Popular Algorithms' 카테고리의 다른 글

karatsuba algorithm  (0) 2016.06.21
Maximum subarray problem  (0) 2016.06.03