874. 模拟行走机器人
题目:
机器人在一个无限大小的 XY 网格平面上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令 commands :
-2 :向左转 90 度
-1 :向右转 90 度
1 <= x <= 9 :向前移动 x 个单位长度
在网格上有一些格子被视为障碍物 obstacles 。第 i 个障碍物位于网格点 obstacles[i] = (xi, yi) 。
机器人无法走到障碍物上,它将会停留在障碍物的前一个网格方块上,但仍然可以继续尝试进行该路线的其余部分。
返回从原点到机器人所有经过的路径点(坐标为整数)的最大欧式距离的平方。(即,如果距离为 5 ,则返回 25 )
注意:
北表示 +Y 方向。
东表示 +X 方向。
南表示 -Y 方向。
西表示 -X 方向。
示例 1:
输入:commands = [4,-1,3], obstacles = []
输出:25
解释:
机器人开始位于 (0, 0):
1. 向北移动 4 个单位,到达 (0, 4)
2. 右转
3. 向东移动 3 个单位,到达 (3, 4)
距离原点最远的是 (3, 4) ,距离为 + = 25
示例 2:
输入:commands = [4,-1,4,-2,4], obstacles = [[2,4]]
输出:65
解释:机器人开始位于 (0, 0):
1. 向北移动 4 个单位,到达 (0, 4)
2. 右转
3. 向东移动 1 个单位,然后被位于 (2, 4) 的障碍物阻挡,机器人停在 (1, 4)
4. 左转
5. 向北走 4 个单位,到达 (1, 8)
距离原点最远的是 (1, 8) ,距离为 + = 65
提示:
1 <= commands.length <=
commands[i] is one of the values in the list [-2,-1,1,2,3,4,5,6,7,8,9].
0 <= obstacles.length <=
-3 * <= xi, yi <= 3 *
答案保证小于
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/walking-robot-simulation
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
首先,使用两个map,x_map: key为障碍物x坐标,val为障碍物y坐标;y_map: key为障碍物y坐标,val为障碍物x坐标;这样做的目的是,由于每次行走都是沿着x或y轴方向,不存在走斜线,因此两个map帮助寻找只沿着x轴或者y轴方向某根直线的障碍物,提高效率。
其次,每一步走的时候,进行障碍物检测。注意需要分清沿着正方向还是负方向走。
最后,得到最后走的距离的最大值返回即可。
代码:
class Solution {
public:
enum Direction
{
up = 1,
down = 2,
left = 3,
right = 4
};
void turnRight(Direction& direction)
{
if(direction == Direction::up)
direction = Direction::right;
else if(direction == Direction::down)
direction = Direction::left;
else if(direction == Direction::left)
direction = Direction::up;
else if(direction == Direction::right)
direction = Direction::down;
}
void turnLeft(Direction& direction)
{
if(direction == Direction::up)
direction = Direction::left;
else if(direction == Direction::down)
direction = Direction::right;
else if(direction == Direction::left)
direction = Direction::down;
else if(direction == Direction::right)
direction = Direction::up;
}
int collisionDetectionAndMove(int start,int end,set<int>& obs)
{
bool collision = false;
int dist = INT_MAX,after_move;
for(const auto& o : obs)
{
if(o == start)
continue;
if((o - start) * (o - end) <= 0)
{
collision = true;
int cur_after_move = start < o ? o - 1 : o + 1;
if(abs(o - start) < dist)
{
dist = abs(o - start);
after_move = cur_after_move;
}
}
}
if(!collision)
return end;
else
return after_move;
}
void proceed(Direction& direction,pair<int,int>& current,int command,unordered_map<int,set<int>>& x_map,unordered_map<int,set<int>>& y_map,int& max_dist_square)
{
if(direction == Direction::up)
current.second = collisionDetectionAndMove(current.second,current.second + command,x_map[current.first]);
else if(direction == Direction::down)
current.second = collisionDetectionAndMove(current.second,current.second - command,x_map[current.first]);
else if(direction == Direction::left)
current.first = collisionDetectionAndMove(current.first,current.first - command,y_map[current.second]);
else if(direction == Direction::right)
current.first = collisionDetectionAndMove(current.first,current.first + command,y_map[current.second]);
int current_dist_square = pow(current.first,2) + pow(current.second,2);
if(current_dist_square > max_dist_square)
max_dist_square = current_dist_square;
}
int robotSim(vector<int>& commands, vector<vector<int>>& obstacles) {
unordered_map<int,set<int>> x_map,y_map;
Direction direction = Direction::up;
pair<int,int> current = {0,0};
int max_dist_square = 0;
for(const auto& vec : obstacles)
{
x_map[vec[0]].insert(vec[1]);
y_map[vec[1]].insert(vec[0]);
}
for(const auto& command : commands)
{
if(command == -2)
turnLeft(direction);
else if(command == -1)
turnRight(direction);
else
proceed(direction,current,command,x_map,y_map,max_dist_square);
}
return max_dist_square;
}
};