Campus Bikes II in Python

The Campus Bikes II problem involves assigning unique bikes to workers on a 2D grid such that the total Manhattan distance is minimized. Given N workers and M bikes (where N ? M), we need to find the optimal assignment.

The Manhattan distance between two points p1 and p2 is calculated as: |p1.x - p2.x| + |p1.y - p2.y|.

Problem Example

Given workers = [[0,0],[2,1]] and bikes = [[1,2],[3,3]]:

Worker1 (0,0) Worker2 (2,1) Bike1 (1,2) Bike2 (3,3) Optimal Assignment: Total Distance = 6

The optimal assignment gives us a minimum total Manhattan distance of 6.

Solution Approach

We use dynamic programming with memoization and backtracking to explore all possible assignments:

  1. Helper function: Calculates Manhattan distance between two points
  2. Recursive solver: Tries assigning each available bike to the current worker
  3. Memoization: Stores results to avoid recalculating the same state
  4. Backtracking: Unmarking bikes after trying each assignment

Implementation

class Solution:
    def helper(self, a, b):
        """Calculate Manhattan distance between two points"""
        return abs(a[0] - b[0]) + abs(a[1] - b[1])
    
    def solve(self, bikes, workers, bikev, i=0):
        """Recursively find minimum distance assignment"""
        info = (i, tuple(bikev))
        
        if info in self.memo:
            return self.memo[info]
        
        if i == len(workers):
            return 0
        
        temp = float('inf')
        
        for j in range(len(bikes)):
            if not bikev[j]:  # If bike j is available
                bikev[j] = True  # Mark bike as used
                current_distance = self.helper(workers[i], bikes[j])
                remaining_distance = self.solve(bikes, workers, bikev, i + 1)
                temp = min(temp, current_distance + remaining_distance)
                bikev[j] = False  # Backtrack: mark bike as available
        
        self.memo[info] = temp
        return temp
    
    def assignBikes(self, workers, bikes):
        """Main function to assign bikes to workers"""
        bikev = [False for _ in range(len(bikes))]
        self.memo = {}
        return self.solve(bikes, workers, bikev)

# Test the solution
solution = Solution()
workers = [[0,0],[2,1]]
bikes = [[1,2],[3,3]]
result = solution.assignBikes(workers, bikes)
print(f"Minimum total Manhattan distance: {result}")
Minimum total Manhattan distance: 6

How It Works

The algorithm works by:

  1. State representation: Current worker index + which bikes are used
  2. Base case: When all workers are assigned, return 0
  3. Recursive case: Try assigning each available bike to current worker
  4. Memoization: Cache results using (worker_index, bikes_used_tuple) as key

Time Complexity

Aspect Complexity Explanation
Time O(N × 2^M) N workers, 2^M possible bike states
Space O(N × 2^M) Memoization table size

Conclusion

This solution uses dynamic programming with memoization to efficiently solve the Campus Bikes II problem. The backtracking approach explores all possible assignments while memoization prevents redundant calculations, ensuring optimal bike-to-worker assignment with minimum total Manhattan distance.

Updated on: 2026-03-25T12:25:15+05:30

334 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements