{x}
blog image

Campus Bikes II

Solution Explanation for Campus Bikes II

This problem asks to find the minimum sum of Manhattan distances between workers and bikes, assigning one unique bike to each worker. The constraints (n ≤ m ≤ 10) suggest a solution using bit manipulation and dynamic programming. A brute-force approach would be computationally expensive for larger inputs.

Approach:

We use dynamic programming with bitmasking to efficiently explore all possible assignments.

  • State: dp[i][mask] represents the minimum total Manhattan distance achievable after assigning bikes to the first i workers, where mask is a bitmask representing which bikes have already been assigned. A bit set to 1 indicates the bike is assigned, and 0 indicates it's not.

  • Base Case: dp[0][0] = 0. No workers assigned, no bikes used, zero distance.

  • Transition: For each worker i and mask mask, we iterate through all possible bikes k. If bike k is not already assigned (bit k is 0 in mask), we calculate the Manhattan distance between worker i and bike k. The minimum distance for this state is then the minimum between the current value and the distance from the previous state (assigning bikes to workers 0 to i-1 with mask mask ^ (1 << k) which removes bike k from the mask) plus the newly calculated distance.

  • Result: The minimum total Manhattan distance is the minimum value in the last row of the dp array (dp[n], where n is the number of workers).

Time Complexity Analysis:

  • The outer loop iterates through the number of workers (n).
  • The second loop iterates through all possible bitmasks (2m).
  • The inner loop iterates through the number of bikes (m).

Therefore, the overall time complexity is O(n * 2m * m). Due to the constraint m ≤ 10, this remains relatively efficient.

Space Complexity Analysis:

The space complexity is determined by the size of the dp array, which is O(n * 2m).

Code Explanation (Python):

class Solution:
    def assignBikes(self, workers: List[List[int]], bikes: List[List[int]]) -> int:
        n, m = len(workers), len(bikes)
        f = [[float('inf')] * (1 << m) for _ in range(n + 1)]  # Initialize dp array with infinity
        f[0][0] = 0  # Base case
 
        for i, (x1, y1) in enumerate(workers, 1):  # Iterate through workers
            for j in range(1 << m):  # Iterate through bitmasks
                for k, (x2, y2) in enumerate(bikes):  # Iterate through bikes
                    if (j >> k) & 1:  # Check if bike k is already assigned
                        f[i][j] = min(  # Update dp array with minimum distance
                            f[i][j],
                            f[i - 1][j ^ (1 << k)] + abs(x1 - x2) + abs(y1 - y2)
                        )
        return min(f[n]) #Return minimum distance from the last row.
 

The other language solutions follow the same logic, adapting the syntax and data structures to their respective languages. The core dynamic programming and bit manipulation techniques remain consistent.