房间(用格栅表示)中有一个扫地机器人。格栅中的每一个格子有空和障碍物两种可能。
扫地机器人提供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的初始位置出发。在左上角的一行以下,三列以右。
注意:
- 输入只用于初始化房间和机器人的位置。你需要“盲解”这个问题。换而言之,你必须在对房间和机器人位置一无所知的情况下,只使用4个给出的API解决问题。
- 扫地机器人的初始位置一定是空地。
- 扫地机器人的初始方向向上。
- 所有可抵达的格子都是相连的,亦即所有标记为1的格子机器人都可以抵达。
- 可以假定格栅的四周都被墙包围。
方法一:DFS
我们不妨假设机器人的初始位置为
时间复杂度
# """
# 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 dfs(i, j, d):
vis.add((i, j))
robot.clean()
for k in range(4):
nd = (d + k) % 4
x, y = i + dirs[nd], j + dirs[nd + 1]
if (x, y) not in vis and robot.move():
dfs(x, y, nd)
robot.turnRight()
robot.turnRight()
robot.move()
robot.turnRight()
robot.turnRight()
robot.turnRight()
dirs = (-1, 0, 1, 0, -1)
vis = set()
dfs(0, 0, 0)
/**
* // 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 int[] dirs = {-1, 0, 1, 0, -1};
private Set<List<Integer>> vis = new HashSet<>();
private Robot robot;
public void cleanRoom(Robot robot) {
this.robot = robot;
dfs(0, 0, 0);
}
private void dfs(int i, int j, int d) {
robot.clean();
vis.add(List.of(i, j));
for (int k = 0; k < 4; ++k) {
int nd = (d + k) % 4;
int x = i + dirs[nd], y = j + dirs[nd + 1];
if (!vis.contains(List.of(x, y)) && robot.move()) {
dfs(x, y, nd);
robot.turnRight();
robot.turnRight();
robot.move();
robot.turnRight();
robot.turnRight();
}
robot.turnRight();
}
}
}
/**
* // 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) {
int dirs[5] = {-1, 0, 1, 0, -1};
set<pair<int, int>> vis;
function<void(int, int, int)> dfs = [&](int i, int j, int d) {
robot.clean();
vis.insert({i, j});
for (int k = 0; k < 4; ++k) {
int nd = (d + k) % 4;
int x = i + dirs[nd], y = j + dirs[nd + 1];
if (!vis.count({x, y}) && robot.move()) {
dfs(x, y, nd);
robot.turnRight();
robot.turnRight();
robot.move();
robot.turnRight();
robot.turnRight();
}
robot.turnRight();
}
};
dfs(0, 0, 0);
}
};
/**
* // 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) {
vis := map[[2]int]bool{}
dirs := [5]int{-1, 0, 1, 0, -1}
var dfs func(int, int, int)
dfs = func(i, j, d int) {
vis[[2]int{i, j}] = true
robot.Clean()
for k := 0; k < 4; k++ {
nd := (d + k) % 4
x, y := i+dirs[nd], j+dirs[nd+1]
if !vis[[2]int{x, y}] && robot.Move() {
dfs(x, y, nd)
robot.TurnRight()
robot.TurnRight()
robot.Move()
robot.TurnRight()
robot.TurnRight()
}
robot.TurnRight()
}
}
dfs(0, 0, 0)
}
/**
* class 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.
* move(): boolean {}
*
* // Robot will stay in the same cell after calling turnLeft/turnRight.
* // Each turn will be 90 degrees.
* turnRight() {}
*
* // Robot will stay in the same cell after calling turnLeft/turnRight.
* // Each turn will be 90 degrees.
* turnLeft() {}
*
* // Clean the current cell.
* clean(): {}
* }
*/
function cleanRoom(robot: Robot) {
const dirs = [-1, 0, 1, 0, -1];
const vis = new Set<string>();
const dfs = (i: number, j: number, d: number) => {
vis.add(`${i}-${j}`);
robot.clean();
for (let k = 0; k < 4; ++k) {
const nd = (d + k) % 4;
const [x, y] = [i + dirs[nd], j + dirs[nd + 1]];
if (!vis.has(`${x}-${y}`) && robot.move()) {
dfs(x, y, nd);
robot.turnRight();
robot.turnRight();
robot.move();
robot.turnRight();
robot.turnRight();
}
robot.turnRight();
}
};
dfs(0, 0, 0);
}