Given a robot cleaner in a room modeled as a grid.html
Each cell in the grid can be empty or blocked.git
The robot cleaner with 4 given APIs can move forward, turn left or turn right. Each turn it made is 90 degrees.github
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:post
這道題就是經典的掃地機器人的題目了,以前常常在地裏看到這道題,終於被 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 函數。若是用過掃地機器人的童鞋應該會有影響,當前方有障礙物的時候,機器人圓盤會先轉個方向,而後再繼續前進,這裏要實現的機制也是相似的,參見代碼以下:this
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/489url
相似題目:
參考資料:
https://leetcode.com/problems/robot-room-cleaner/
https://leetcode.com/problems/robot-room-cleaner/discuss/153530/9ms-Java-with-Explanations