列表

详情


489. 扫地机器人

房间(用格栅表示)中有一个扫地机器人。格栅中的每一个格子有空和障碍物两种可能。

扫地机器人提供4个API,可以向前进,向左转或者向右转。每次转弯90度。

当扫地机器人试图进入障碍物格子时,它的碰撞传感器会探测出障碍物,使它停留在原地。

请利用提供的4个API编写让机器人清理整个房间的算法。

interface Robot {
  // 若下一个方格为空,则返回true,并移动至该方格
  // 若下一个方格为障碍物,则返回false,并停留在原地
  boolean move();

  // 在调用turnLeft/turnRight后机器人会停留在原位置
  // 每次转弯90度
  void turnLeft();
  void turnRight();

  // 清理所在方格
  void clean();
}

示例:

输入:
room = [
  [1,1,1,1,1,0,1,1],
  [1,1,1,1,1,0,1,1],
  [1,0,1,1,1,1,1,1],
  [0,0,0,1,0,0,0,0],
  [1,1,1,1,1,1,1,1]
],
row = 1,
col = 3

解析:
房间格栅用0或1填充。0表示障碍物,1表示可以通过。
机器人从row=1,col=3的初始位置出发。在左上角的一行以下,三列以右。

注意:

  1. 输入只用于初始化房间和机器人的位置。你需要“盲解”这个问题。换而言之,你必须在对房间和机器人位置一无所知的情况下,只使用4个给出的API解决问题。 
  2. 扫地机器人的初始位置一定是空地。
  3. 扫地机器人的初始方向向上。
  4. 所有可抵达的格子都是相连的,亦即所有标记为1的格子机器人都可以抵达。
  5. 可以假定格栅的四周都被墙包围。

相似题目

墙与门

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
/** * // This is the robot's control interface. * // You should not implement it, or speculate about its implementation * class Robot { * public: * // Returns true if the cell in front is open and robot moves into the cell. * // Returns false if the cell in front is blocked and robot stays in the current cell. * bool move(); * * // Robot will stay in the same cell after calling turnLeft/turnRight. * // Each turn will be 90 degrees. * void turnLeft(); * void turnRight(); * * // Clean the current cell. * void clean(); * }; */ class Solution { public: void cleanRoom(Robot& robot) { } };

golang 解法, 执行用时: 4 ms, 内存消耗: 4.3 MB, 提交时间: 2023-10-21 19:00:31

/**
 * // This is the robot's control interface.
 * // You should not implement it, or speculate about its implementation
 * type Robot struct {
 * }
 * 
 * // Returns true if the cell in front is open and robot moves into the cell.
 * // Returns false if the cell in front is blocked and robot stays in the current cell.
 * func (robot *Robot) Move() bool {}
 *
 * // Robot will stay in the same cell after calling TurnLeft/TurnRight.
 * // Each turn will be 90 degrees.
 * func (robot *Robot) TurnLeft() {}
 * func (robot *Robot) TurnRight() {}
 *
 * // Clean the current cell.
 * func (robot *Robot) Clean() {}
 */

func cleanRoom(robot *Robot) {
	visited := map[[2]int]bool{}
	// 思维误区:考虑方向,顺时针=> 0:up  1:right  2: down, 3:left
	dirs := [][]int{[]int{-1,0}, []int{0,1}, []int{1,0}, []int{0,-1}}
	var dfs func(cur [2]int, direction int)
	dfs = func(cur [2]int, direction int){
		visited[cur] = true
		robot.Clean()
		// 思维误区:考虑方向,顺时针: 0: 'up', 1: 'right', 2: 'down', 3: 'left'
		for i := range dirs{
			next_dir := (direction+i) % 4
			next := [2]int{cur[0]+dirs[next_dir][0], cur[1]+dirs[next_dir][1]}
			if !visited[next] && robot.Move(){
				dfs(next, next_dir)
				// 此处递归回来后,robot 要回到原位置 并恢复朝向
				robot.TurnLeft()
				robot.TurnLeft()
				robot.Move()
				robot.TurnLeft()
				robot.TurnLeft()
			}
			// turn the robot following chosen direction : clockwise
			// 所以前提要求 robot 方向要恢复
			robot.TurnRight()
		}
	}
	dfs([2]int{0,0}, 0)// 0 向前
}

java 解法, 执行用时: 11 ms, 内存消耗: 43 MB, 提交时间: 2023-10-21 19:00:04

/**
 * // This is the robot's control interface.
 * // You should not implement it, or speculate about its implementation
 * interface Robot {
 *     // Returns true if the cell in front is open and robot moves into the cell.
 *     // Returns false if the cell in front is blocked and robot stays in the current cell.
 *     public boolean move();
 *
 *     // Robot will stay in the same cell after calling turnLeft/turnRight.
 *     // Each turn will be 90 degrees.
 *     public void turnLeft();
 *     public void turnRight();
 *
 *     // Clean the current cell.
 *     public void clean();
 * }
 */
class Solution {
    private final int[][] ds = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    public void cleanRoom(Robot robot) {
        dfs(robot, 0, 0, 0, new HashSet<String>());     // 把机器人的初始坐标视为原点,初始方向朝上
    }

    private void dfs(Robot robot, int x, int y, int d, Set<String> visited) {
        // 机器人先打扫完当前位置
        visited.add(x + "," + y);
        robot.clean();
        // 然后尝试往四个方向走
        for(int i = 0; i < 4; i++){
            int nd = (d + i) % 4;
            int nextX = x + ds[nd][0], nextY = y + ds[nd][1];
            if(!visited.contains(nextX + "," + nextY) && robot.move()){
                // 如果下一个位置没走过且不是障碍,就前往打扫
                dfs(robot, nextX, nextY, nd, visited);
            }
            robot.turnRight();
        }
        // 机器人退回到上一个位置(它进来前的位置,且保持进来时的朝向),相当于回溯
        robot.turnRight();
        robot.turnRight();
        robot.move();
        robot.turnLeft();
        robot.turnLeft();
    }
}

cpp 解法, 执行用时: 8 ms, 内存消耗: 8.8 MB, 提交时间: 2023-10-21 18:59:16

/**
 * // This is the robot's control interface.
 * // You should not implement it, or speculate about its implementation
 * class Robot {
 *   public:
 *     // Returns true if the cell in front is open and robot moves into the cell.
 *     // Returns false if the cell in front is blocked and robot stays in the current cell.
 *     bool move();
 *
 *     // Robot will stay in the same cell after calling turnLeft/turnRight.
 *     // Each turn will be 90 degrees.
 *     void turnLeft();
 *     void turnRight();
 *
 *     // Clean the current cell.
 *     void clean();
 * };
 */

struct PairHash {   // 自定义hash函数
    size_t operator()(const pair<int, int>& key) const {
        return hash<int>{}(key.first * 131) ^ hash<int>{}(key.second);
    }
};

class Solution {
    int dirs[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};
    unordered_set<pair<int, int>, PairHash> vis;    // 防止重复访问
public:
    void cleanRoom(Robot& robot) {
        dfs(robot, 0, 0, 0);
    }

    void dfs(Robot& robot, int x, int y, int di) {
        vis.emplace(x, y);  // 标记为已访问
        robot.clean();
        for (int i = 0; i < 4; ++i) {
            int nd = (i + di) % 4, nx = x + dirs[nd][0], ny = y + dirs[nd][1];
            if (vis.count(make_pair(nx, ny)) == 0 && robot.move()) {
                dfs(robot, nx, ny, nd);

                // 回溯
                robot.turnRight();
                robot.turnRight();
                robot.move();   // 移动过的一步,再移动回来
                robot.turnRight();
                robot.turnRight();
            }
            robot.turnRight();
        }
    }
};

java 解法, 执行用时: 13 ms, 内存消耗: 42.3 MB, 提交时间: 2023-10-21 18:58:49

/**
 * // This is the robot's control interface.
 * // You should not implement it, or speculate about its implementation
 * interface Robot {
 *     // Returns true if the cell in front is open and robot moves into the cell.
 *     // Returns false if the cell in front is blocked and robot stays in the current cell.
 *     public boolean move();
 *
 *     // Robot will stay in the same cell after calling turnLeft/turnRight.
 *     // Each turn will be 90 degrees.
 *     public void turnLeft();
 *     public void turnRight();
 *
 *     // Clean the current cell.
 *     public void clean();
 * }
 */

public class Pair<F, S> {
    public F first;
    public S second;

    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }

    @Override
    public boolean equals(Object o) {
        Pair<F, S> p = (Pair<F, S>) o;
        return Objects.equals(p.first, first) && Objects.equals(p.second, second);
    }

    @Override
    public int hashCode() {
        return first.hashCode() ^ second.hashCode();
    }
}

class Solution {
    // going clockwise : 0: 'up', 1: 'right', 2: 'down', 3: 'left'
    int[][] directions = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    Set<Pair<Integer, Integer>> visited = new HashSet();
    Robot robot;

    public void goBack() {
        robot.turnRight();
        robot.turnRight();
        robot.move();
        robot.turnRight();
        robot.turnRight();
    }

    public void backtrack(int row, int col, int d) {
        visited.add(new Pair(row, col));
        robot.clean();
        // going clockwise : 0: 'up', 1: 'right', 2: 'down', 3: 'left'
        for (int i = 0; i < 4; ++i) {
            int newD = (d + i) % 4;
            int newRow = row + directions[newD][0];
            int newCol = col + directions[newD][1];

            if (!visited.contains(new Pair(newRow, newCol)) && robot.move()) {
                backtrack(newRow, newCol, newD);
                goBack();
            }
            // turn the robot following chosen direction : clockwise
            robot.turnRight();
        }
    }

    public void cleanRoom(Robot robot) {
        this.robot = robot;
        backtrack(0, 0, 0);
    }
}

python3 解法, 执行用时: 72 ms, 内存消耗: 17.3 MB, 提交时间: 2023-10-21 18:42:00

# """
# This is the robot's control interface.
# You should not implement it, or speculate about its implementation
# """
#class Robot:
#    def move(self):
#        """
#        Returns true if the cell in front is open and robot moves into the cell.
#        Returns false if the cell in front is blocked and robot stays in the current cell.
#        :rtype bool
#        """
#
#    def turnLeft(self):
#        """
#        Robot will stay in the same cell after calling turnLeft/turnRight.
#        Each turn will be 90 degrees.
#        :rtype void
#        """
#
#    def turnRight(self):
#        """
#        Robot will stay in the same cell after calling turnLeft/turnRight.
#        Each turn will be 90 degrees.
#        :rtype void
#        """
#
#    def clean(self):
#        """
#        Clean the current cell.
#        :rtype void
#        """

class Solution:       
    def cleanRoom(self, robot):
        """
        :type robot: Robot
        :rtype: None
        """
        def go_back():
            robot.turnRight()
            robot.turnRight()
            robot.move()
            robot.turnRight()
            robot.turnRight()
            
        def backtrack(cell = (0, 0), d = 0):
            visited.add(cell)
            robot.clean()
            # going clockwise : 0: 'up', 1: 'right', 2: 'down', 3: 'left'
            for i in range(4):
                new_d = (d + i) % 4
                new_cell = (cell[0] + directions[new_d][0], \
                            cell[1] + directions[new_d][1])
                
                if not new_cell in visited and robot.move():
                    backtrack(new_cell, new_d)
                    go_back()
                # turn the robot following chosen direction : clockwise
                robot.turnRight()
    
        # going clockwise : 0: 'up', 1: 'right', 2: 'down', 3: 'left'
        directions = [(-1, 0), (0, 1), (1, 0), (0, -1)]
        visited = set()
        backtrack()

上一题