![]() |
VOOZH | about |
Given a 2d matrix cost[][] of dimensions n * n where cost[i][j] denotes the cost of moving from city i to city j. Find the minimum cost to complete a tour from city 0 (0-based index) to all other cities such that we visit each city exactly once and then at the end come back to city 0.
Examples:
Input: cost[][] = [[0, 111],
[112, 0]]
Output: 223
Explanation: We can visit 0->1->0 and cost = 111 + 112 = 223.Input: cost[][] = [[0, 10, 15, 20],
[10, 0, 35, 25],
[15, 35, 0, 30],
[20, 25, 30, 0]]
Output: 80
Explanation: We can visit 0->2->3->1->0 and cost = 15 + 30 + 25+ 10= 80.
Table of Content
The idea is to consider all possible routes that start at city 0, visit every other city exactly once, and finally return to city 0. For each route, we keep track of which cities have been visited and the current city, then accumulate the travel cost as we move to the next city. After evaluating every valid route, we choose the one with the smallest total cost.
80
Bitmask Representation for Tracking Visited Cities :-
To keep track of which cities have been visited, we use an integer called mask, where each bit represents a city. If the i-th bit is set, it means the i-th city has been visited; if it is not set, the city is still unvisited. The maximum possible value of the mask is 2n-1 + 2n-2+ ... 21+20 = 2n-1, when all cities have been visited. This representation ensures that each city is visited exactly once, and a path is considered complete when all bits are set and we return to city 0.
The idea is to try every possible way of visiting all cities exactly once and returning to city 0.
We use a bitmask to keep track of which cities have been visited so far, and from the current city, we recursively try going to any city that is still unvisited. By exploring all valid routes in this way and adding up their travel costs, we will find the minimum cost among them.
80
In the above recursive solution, we can see that the same subproblem is computed multiple times. The subproblem is fully defined by two things:
Different routes can lead to the same combination of these two values. For example, consider a state where the mask shows that cities 0, 1, 2, and 4 have been visited, and the current city is 4. This state might be reached by:
Even though the arrival order differs, once we are at city 4 with exactly these cities visited, the remaining task is identical. The set of unvisited cities is the same, and the next decisions do not depend on the earlier path.
To optimize this, we store the answer for each (current city, mask) state in a DP table. If the same state appears again, we directly use the stored value instead of recomputing it.
80
Instead of using recursion we can use iterative DP. We define dp[mask][i] as the minimum cost to visit all cities in the subset represented by mask and end at city i. Initially, only city 0 is visited, so dp[1][0] = 0.
We iterate over all masks representing subsets of cities. For each mask and each city i already included in mask, we try visiting every city j not yet in mask. The new mask nxt = mask | (1 << j) represents the updated set of visited cities, and we update dp[nxt][j] as:
dp[nxt][j] = min(dp[nxt][j], dp[mask][i] + cost[i][j])
This ensures that we consider the minimum cost to reach city j after visiting the cities in mask. After filling the DP table, the answer is the minimum cost to visit all cities (fullMask) and return to city 0:
ans = min(ans, dp[fullMask][i] + cost[i][0]) for all i from 0 to n - 1
80