diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/BitmaskDP.java b/src/main/java/com/thealgorithms/dynamicprogramming/BitmaskDP.java new file mode 100644 index 000000000000..8c731bcae2f9 --- /dev/null +++ b/src/main/java/com/thealgorithms/dynamicprogramming/BitmaskDP.java @@ -0,0 +1,76 @@ +package com.thealgorithms.dynamicprogramming; + +import java.util.Arrays; + +/** + * An implementation of Dynamic Programming using Bitmasks. + * Bitmask DP represents a subset of elements as bits in an integer. + * If the i-th bit is 1, the i-th element is included in the subset. + * This is highly effective for problems where n is small (≤ 20). + * This class demonstrates Bitmask DP by solving the Traveling + * Salesperson Problem (TSP) - finding the minimum cost to visit all + * nodes exactly once and return to the starting node. + */ +public final class BitmaskDP { + + private BitmaskDP() { + // Prevent instantiation + } + + /** + * Solves the Traveling Salesperson Problem using Bitmask DP. + * @param distance A 2D array where distance[i][j] is the cost to travel from node i to node j. + * @return The minimum distance to visit all nodes and return to the start. + */ + public static int tsp(int[][] distance) { + int n = distance.length; + if (n == 0) { + return 0; + } + + int totalSubsets = 1 << n; + + // dp[mask][i] = min distance visiting the subset 'mask' and currently ending at node 'i' + int[][] dp = new int[totalSubsets][n]; + + // Initialize with Integer.MAX_VALUE + for (int[] row : dp) { + Arrays.fill(row, Integer.MAX_VALUE); + } + + // Base case: Start at node 0. + dp[1][0] = 0; + + for (int mask = 1; mask < totalSubsets; mask++) { + for (int u = 0; u < n; u++) { + // Skip if node 'u' is NOT in the current subset, + // OR if the current state is unreachable (INT_MAX) + if ((mask & (1 << u)) == 0 || dp[mask][u] == Integer.MAX_VALUE) { + continue; + } + + for (int v = 0; v < n; v++) { + // If node 'v' IS already in the subset, skip + if ((mask & (1 << v)) != 0) { + continue; + } + + int nextMask = mask | (1 << v); + + // Safe to add since we already verified dp[mask][u] is not INT_MAX + dp[nextMask][v] = Math.min(dp[nextMask][v], dp[mask][u] + distance[u][v]); + } + } + } + + // Find the minimum cost to return to the starting node (0) from the last visited node + int minCost = Integer.MAX_VALUE; + int allVisitedMask = totalSubsets - 1; // All n bits are 1 + + for (int i = 1; i < n; i++) { + minCost = Math.min(minCost, dp[allVisitedMask][i] + distance[i][0]); + } + + return minCost; + } +} diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/BitmaskDP_README.md b/src/main/java/com/thealgorithms/dynamicprogramming/BitmaskDP_README.md new file mode 100644 index 000000000000..a3391663783c --- /dev/null +++ b/src/main/java/com/thealgorithms/dynamicprogramming/BitmaskDP_README.md @@ -0,0 +1,97 @@ +This document provides a detailed, line-by-line breakdown of the Traveling Salesperson Problem (TSP) implementation using Bitmask Dynamic Programming. + +Class: BitmaskDP + +A utility class containing the algorithm to solve the TSP. It is declared as final with a private constructor to prevent instantiation, adhering to standard Java utility class conventions. + +Method: tsp(int[][] distance) + +Calculates the minimum cost to visit every node exactly once and return to the starting node. + +Parameters + +distance (int[][]): An $N \times N$ adjacency matrix representing the graph. distance[u][v] holds the cost/distance to travel from node u to node v. + +Returns + +int: The minimum total distance required to complete the TSP tour. + +Variable Breakdown + +n: The total number of nodes (cities) in the graph. + +totalSubsets: Calculated as 1 << n (which equals $2^n$). This represents the total number of possible combinations of visited nodes. + +dp: A 2D array of size [totalSubsets][n]. + +mask (row): The current subset of visited nodes represented as an integer bitmask. + +i (column): The node the path currently ends on. + +dp[mask][i] stores the minimum cost to reach this state. + +Step-by-Step Logic + +1. Initialization + +for (int[] row : dp) { + Arrays.fill(row, Integer.MAX_VALUE); +} + + +All states in the DP table are initialized to Integer.MAX_VALUE (infinity). This indicates that, initially, all paths are considered unreachable. + +2. The Base Case + +dp[1][0] = 0; + + +The algorithm assumes node 0 is the starting point. + +The binary representation of 1 is ...0001, meaning only the 0-th bit is set (only node 0 has been visited). + +The cost to be at node 0 having only visited node 0 is 0. + +3. State Transitions (The Core Loop) + +The algorithm iterates through every possible mask (from 1 to totalSubsets - 1). + +for (int u = 0; u < n; u++) { + if ((mask & (1 << u)) == 0 || dp[mask][u] == Integer.MAX_VALUE) continue; + + +For each mask, it checks every node u to see if it acts as a valid "current end node". It skips the iteration if: + +Node u is not in the current mask. + +The state dp[mask][u] is unreachable (Integer.MAX_VALUE). + +for (int v = 0; v < n; v++) { + if ((mask & (1 << v)) != 0) continue; + + +It then looks for an unvisited adjacent node v. If v is already included in the mask (meaning the bit is 1), it skips v because the TSP requires visiting nodes exactly once. + +int nextMask = mask | (1 << v); +dp[nextMask][v] = Math.min(dp[nextMask][v], dp[mask][u] + distance[u][v]); + + +If v is unvisited, the algorithm calculates the nextMask by setting the $v$-th bit to 1. It then updates the DP table for nextMask ending at v with the minimum of: + +Its current known cost. + +The cost of the current state (dp[mask][u]) plus the travel cost from u to v. + +4. Calculating the Final Tour Cost + +int minCost = Integer.MAX_VALUE; +int allVisitedMask = totalSubsets - 1; + +for (int i = 1; i < n; i++) { + minCost = Math.min(minCost, dp[allVisitedMask][i] + distance[i][0]); +} + + +After the DP table is fully populated, the algorithm looks at the state where all nodes have been visited (allVisitedMask, where all $N$ bits are 1). + +It iterates through every possible ending node i, taking the cost of reaching that node and adding the distance to travel back to the starting node 0 (distance[i][0]). The smallest resulting sum is returned as the final minCost. \ No newline at end of file