关于在2D网格中以常数时间复杂度实现多机器人同步移动的算法问询
Awesome question! Let's figure out how to get constant-time (relative to grid size) robot movements instead of the O(width*height) approach you're currently using. The key is to stop relying on iterating over the entire grid for every move—instead, we'll track robots and the flag using efficient data structures that let us compute state changes directly.
Core Insight
The O(width*height) cost comes from scanning every cell in the grid on each move. To fix this, we can abandon maintaining the full grid state after initialization. Instead:
- Store all active robots' coordinates in a dictionary (to track robot IDs like R1/R2) or a hash set (if only coordinates matter).
- Store the flag's fixed coordinate as a single tuple.
This way, every move operation only touches the robots that are still active, not every cell in the grid.
Step-by-Step Implementation
1. Initialization (One-Time O(width*height) Cost)
First, we process the input grid once to extract our initial state:
- Iterate through each cell in the grid.
- For every robot (marked with R1, R2, etc.), map their ID to their (x, y) coordinate in a dictionary.
- Record the flag's (x, y) coordinate.
This is a one-time setup cost, and all subsequent moves will avoid grid traversal entirely.
2. Handling Each Move (O(N) Time, N = Number of Active Robots)
For any direction (left/right/up/down), we first define the coordinate offset for that direction:
- Left:
dx = -1, dy = 0 - Right:
dx = 1, dy = 0 - Up:
dx = 0, dy = -1 - Down:
dx = 0, dy = 1
Then, we compute the new state in three parts:
- Saved Robots: Identify all robots whose new position (x+dx, y+dy) matches the flag's coordinate. Collect these robot IDs, then mark them for removal.
- Eliminated Robots: Identify robots whose new position falls outside the grid boundaries (e.g.,
x+dx < 0orx+dx >= width, same for y). Mark these for removal too. - Remaining Active Robots: Update the coordinates of the remaining robots to their new positions.
Here's a concrete example in Python:
# Initial state derived from your example active_robots = {"R1": (0, 0), "R2": (1, 1)} # Robot ID -> (x, y) flag_pos = (2, 1) width = 2 height = 3 def move(direction): dx, dy = 0, 0 if direction == "left": dx = -1 elif direction == "right": dx = 1 elif direction == "up": dy = -1 elif direction == "down": dy = 1 saved = [] to_remove = set() # Iterate through robots to evaluate their new state for robot_id, (x, y) in active_robots.items(): new_x = x + dx new_y = y + dy # Check if robot reaches the flag if (new_x, new_y) == flag_pos: saved.append(robot_id) to_remove.add(robot_id) continue # Check if robot moves out of bounds if new_x < 0 or new_x >= width or new_y < 0 or new_y >= height: to_remove.add(robot_id) continue # Update position for surviving robots active_robots[robot_id] = (new_x, new_y) # Clean up saved/eliminated robots for robot_id in to_remove: del active_robots[robot_id] if saved: print(f"saved: {saved}")
Why This is "Constant-Time" Relative to Grid Size
Your original approach scales with the grid's total cells (O(width*height)), which gets slow as the grid grows. With this method:
- The time per move depends only on the number of active robots (N), not the grid's dimensions.
- Even if the grid is 1000x1000 but only has 5 robots, each move takes O(5) time—effectively constant relative to the grid size.
This fits exactly what you're asking for: arbitrary direction moves without paying the cost of scanning the entire grid every time.
内容的提问来源于stack exchange,提问作者Noé Mastrorillo




