[LeetCode] 489. Robot Room Cleaner 掃地機器人


 

Given a robot cleaner in a room modeled as a grid.

Each cell in the grid can be empty or blocked.

The robot cleaner with 4 given APIs can move forward, turn left or turn right. Each turn it made is 90 degrees.

When it tries to move into a blocked cell, its bumper sensor detects the obstacle and it stays on the current cell.

Design an algorithm to clean the entire room using only the 4 given APIs shown below.

interface Robot {
  // returns true if next cell is open and robot moves into the cell.
  // returns false if next cell is obstacle and robot stays on the current cell.
  boolean move();

  // Robot will stay on the same cell after calling turnLeft/turnRight.
  // Each turn will be 90 degrees.
  void turnLeft();
  void turnRight();

  // Clean the current cell.
  void clean();
}

Example:

Input:
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

Explanation:
All grids in the room are marked by either 0 or 1.
0 means the cell is blocked, while 1 means the cell is accessible.
The robot initially starts at the position of row=1, col=3.
From the top left corner, its position is one row below and three columns right.

Notes:

  1. The input is only given to initialize the room and the robot's position internally. You must solve this problem "blindfolded". In other words, you must control the robot using only the mentioned 4 APIs, without knowing the room layout and the initial robot's position.
  2. The robot's initial position will always be in an accessible cell.
  3. The initial direction of the robot will be facing up.
  4. All accessible cells are connected, which means the all cells marked as 1 will be accessible by the robot.
  5. Assume all four edges of the grid are all surrounded by wall.

 

這道題就是經典的掃地機器人的題目了,之前經常在地里看到這道題,終於被 LeetCode 收錄了進來了,也總算是找到了一個好的歸宿了。回歸題目,給了我們一個掃地機器人,給了4個 API 函數可供我們調用,具體實現不用我們操心,讓我們實現打掃房間 cleanRoom 函數。給的例子中有房間和起始位置的信息,但是代碼中卻沒有,擺明是不想讓我們被分心。想想也是,難道我們在給掃地機器人編程時,還必須要知道用戶的房間信息么?當然不能夠啦,題目中也說了讓我們盲目 Blindfolded 一些,所以就盲目的寫吧。既然是掃地,那么肯定要記錄哪些位置已經掃過了,所以肯定要記錄位置信息,由於不知道全局位置,那么只能用相對位置信息了。初始時就是 (0, 0),然后上下左右加1減1即可。位置信息就放在一個 HashSet 中就可以了,同時為了方便,還可以將二維坐標編碼成一個字符串。我們采用遞歸 DFS 來做,初始化位置為 (0, 0),然后建一個上下左右的方向數組,使用一個變量 dir 來從中取數。在遞歸函數中,我們首先對起始位置調用 clean 函數,因為題目中說了起始位置是能到達的,即是為1的地方。然后就要把起始位置加入 visited。然后我們循環四次,因為有四個方向,由於遞歸函數傳進來的 dir 是上一次轉到的方向,那么此時我們 dir 加上i,為了防止越界,對4取余,就是我們新的方向了,然后算出新的位置坐標 newX 和 newY。此時先要判斷 visited 不含有這個新位置,即新位置沒有訪問過,還要調用 move 函數來確定新位置是否可以到達,若這兩個條件都滿足的話,我們就對新位置調用遞歸函數。注意遞歸函數調用完成后,我們要回到調用之前的狀態,因為這里的 robot 是帶了引用號的,是全局通用的,所以要回到之前的狀態。回到之前的狀態很簡單,因為這里的機器人的運作方式是先轉到要前進的方向,才能前進。那么我們后退的方法就是,旋轉 180 度,前進一步,再轉回到原來的方向。同理,我們在按順序試上->右->下->左的時候,每次機器人要向右轉一下,因為 move 函數只能探測前方是否能到達,所以我們必須讓機器人轉到正確的方向,才能正確的調用 move 函數。如果用過掃地機器人的童鞋應該會有影響,當前方有障礙物的時候,機器人圓盤會先轉個方向,然后再繼續前進,這里要實現的機制也是類似的,參見代碼如下:

 

class Solution {
public:
    vector<vector<int>> dirs{{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    void cleanRoom(Robot& robot) {
        unordered_set<string> visited;
        helper(robot, 0, 0, 0, visited);
    }
    void helper(Robot& robot, int x, int y, int dir, unordered_set<string>& visited) {
        robot.clean();
        visited.insert(to_string(x) + "-" + to_string(y));
        for (int i = 0; i < 4; ++i) {
            int cur = (i + dir) % 4, newX = x + dirs[cur][0], newY = y + dirs[cur][1];
            if (!visited.count(to_string(newX) + "-" + to_string(newY)) && robot.move()) {
                helper(robot, newX, newY, cur, visited);
                robot.turnRight();
                robot.turnRight();
                robot.move();
                robot.turnLeft();
                robot.turnLeft();
            }
            robot.turnRight();
        }
    }
};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/489

 

類似題目:

Walls and Gates 

 

參考資料:

https://leetcode.com/problems/robot-room-cleaner/

https://leetcode.com/problems/robot-room-cleaner/discuss/153530/9ms-Java-with-Explanations

https://leetcode.com/problems/robot-room-cleaner/discuss/139057/Very-easy-to-understand-Java-solution

https://leetcode.com/problems/robot-room-cleaner/discuss/151942/Java-DFS-Solution-with-Detailed-Explanation-and-6ms-(99)-Solution

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM