diff --git a/DIRECTORY.md b/DIRECTORY.md index b34e8afe6..f19f1c8ac 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -122,6 +122,7 @@ * [Prim](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/prim.cpp) * [Topological Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/topological_sort.cpp) * [Topological Sort By Kahns Algo](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/topological_sort_by_kahns_algo.cpp) + * [Travelling Salesman Problem](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/travelling_salesman_problem.cpp) ## Graphics * [Spirograph](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graphics/spirograph.cpp) diff --git a/graph/travelling_salesman_problem.cpp b/graph/travelling_salesman_problem.cpp new file mode 100644 index 000000000..28df3e931 --- /dev/null +++ b/graph/travelling_salesman_problem.cpp @@ -0,0 +1,111 @@ +/** + * @file + * @brief [Travelling Salesman Problem] + * (https://en.wikipedia.org/wiki/Travelling_salesman_problem) implementation + * + * @author [Mayank Mamgain](http://github.com/Mayank17M) + * + * @details + * Travelling salesman problem asks: + * 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? + * TSP can be modeled as an undirected weighted graph, such that cities are the + * graph's vertices, paths are the graph's edges, and a path's distance is the + * edge's weight. It is a minimization problem starting and finishing at a + * specified vertex after having visited each other vertex exactly once. + * This is the naive implementation of the problem. + */ + +#include /// for std::min +#include /// for assert +#include /// for IO operations +#include /// for limits of integral types +#include /// for std::vector + +/** + * @namespace graph + * @brief Graph Algorithms + */ +namespace graph { +/** + * @brief Function calculates the minimum path distance that will cover all the + * cities starting from the source. + * + * @param cities matrix representation of cities + * @param src Point from where salesman is starting + * @param V number of vertices in the graph + * + */ +int TravellingSalesmanProblem(std::vector> *cities, + int32_t src, uint32_t V) { + //// vtx stores the vertexs of the graph + std::vector vtx; + for (uint32_t i = 0; i < V; i++) { + if (i != src) { + vtx.push_back(i); + } + } + + //// store minimum weight Hamiltonian Cycle. + int32_t min_path = 2147483647; + do { + //// store current Path weight(cost) + int32_t curr_weight = 0; + + //// compute current path weight + int k = src; + for (int i : vtx) { + curr_weight += (*cities)[k][i]; + k = i; + } + curr_weight += (*cities)[k][src]; + + //// update minimum + min_path = std::min(min_path, curr_weight); + + } while (next_permutation(vtx.begin(), vtx.end())); + + return min_path; +} +} // namespace graph + +/** + * @brief Self-test implementations + * @returns void + */ +static void tests() { + std::cout << "Initiatinig Predefined Tests..." << std::endl; + std::cout << "Initiating Test 1..." << std::endl; + std::vector> cities = { + {0, 20, 42, 35}, {20, 0, 30, 34}, {42, 30, 0, 12}, {35, 34, 12, 0}}; + uint32_t V = cities.size(); + assert(graph::TravellingSalesmanProblem(&cities, 0, V) == 97); + std::cout << "1st test passed..." << std::endl; + + std::cout << "Initiating Test 2..." << std::endl; + cities = {{0, 5, 10, 15}, {5, 0, 20, 30}, {10, 20, 0, 35}, {15, 30, 35, 0}}; + V = cities.size(); + assert(graph::TravellingSalesmanProblem(&cities, 0, V) == 75); + std::cout << "2nd test passed..." << std::endl; + + std::cout << "Initiating Test 3..." << std::endl; + cities = { + {0, 10, 15, 20}, {10, 0, 35, 25}, {15, 35, 0, 30}, {20, 25, 30, 0}}; + V = cities.size(); + assert(graph::TravellingSalesmanProblem(&cities, 0, V) == 80); + std::cout << "3rd test passed..." << std::endl; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + tests(); // run self-test implementations + std::vector> cities = { + {0, 5, 10, 15}, {5, 0, 20, 30}, {10, 20, 0, 35}, {15, 30, 35, 0}}; + uint32_t V = cities.size(); + std::cout << graph::TravellingSalesmanProblem(&cities, 0, V) << std::endl; + return 0; +}