机器人在一个无限大小的网格上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令:
-2:向左转 90 度
-1:向右转 90 度
1 <= x <= 9:向前移动 x 个单位长度
在网格上有一些格子被视为障碍物。
第 i 个障碍物位于网格点 (obstacles[i][0], obstacles[i][1])
如果机器人试图走到障碍物上方,那么它将停留在障碍物的前一个网格方块上,但仍然可以继续该路线的其余部分。
返回从原点到机器人的最大欧式距离的平方。
示例 1:
输入: commands = [4,-1,3], obstacles = []
输出: 25
解释: 机器人将会到达 (3, 4)
示例 2:
输入: commands = [4,-1,4,-2,4], obstacles = [[2,4]]
输出: 65
解释: 机器人在左转走到 (1, 8) 之前将被困在 (1, 4) 处
提示:
0 <= commands.length <= 10000
0 <= obstacles.length <= 10000
-30000 <= obstacle[i][0] <= 30000
-30000 <= obstacle[i][1] <= 30000
答案保证小于 2 ^ 31
思路分析:这道题题意比较简单,蛋式涉及到图中点的移动操作,如果不在纸上画一画会比较抽象,所以建议最好在纸上先模拟一下示例的执行过程。
这道题不但涉及到x、y坐标问题,还涉及到转向(东南西北)。方向图如下:
黑色的表示的是二维坐标轴,绿色的表示的平面四个方向,红色的表示的方向标号。
观察上图会发现两个很巧妙的规律:
如果向右转90°,相当于顺时针旋转90°,也就是红色的标号循环自增1;
如果向左转90°,相当于逆时针旋转90°,也就是红色的标号循环自减1(或者自增3)。
这样就巧妙的解决了转向问题。
class Solution {
public:
int robotSim(vector<int>& commands, vector<vector<int>>& obstacles) {
set<pair<int, int>> obstaclesSet;//把vector容器转换成set容器,这样方便查找障碍物
//四个方向{x,y}分别代表北、东、南、西(顺时针一圈)
vector<pair<int, int>> directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
for (const auto &obstacle : obstacles){
obstaclesSet.insert({obstacle[0], obstacle[1]});
}
pair<int, int> nowLoaction = {0, 0};//现在的位置{x,y}
int mixDis = 0, directionIndex = 0;//初始朝向北,所以方向index = 0
//模拟执行所有command
for (auto command : commands){
if (command == -1){//顺时针转向90°
directionIndex = (directionIndex + 1) % 4;
}
else if (command == -2){//逆时针转向90° == 顺时针转向270°
directionIndex = (directionIndex + 3) % 4;
}
else{
//否则执行的行走命令,每次都只向当前方向迈出一步,location增量为{x = directions[directionIndex].first,y = directions[directionIndex].second}
while (--command >= 0 && obstaclesSet.find({nowLoaction.first + directions[directionIndex].first, nowLoaction.second + directions[directionIndex].second}) == obstaclesSet.end()){
//如果当前这一个步没有遇到障碍物,则更新当前location
nowLoaction.first += directions[directionIndex].first;
nowLoaction.second += directions[directionIndex].second;
}
//更新原点到机器人的最大欧式距离的平方
mixDis = max(mixDis, nowLoaction.first * nowLoaction.first + nowLoaction.second * nowLoaction.second);
}
}
return mixDis;
}
};