[LeetCode874. 模拟行走机器人] | 刷题打卡

801 阅读1分钟

一、题目描述:

机器人在一个无限大小的 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) ,距离为 32 + 42 = 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) ,距离为 12 + 82 = 65

二、思路分析:

这题是个easy题,逻辑并不复杂,但是写起来有点麻烦,这里推荐一种用高中数学中向量的方式来处理机器人移动的问题。先建立坐标系,再把方向和移动数据转换成向量运算。

  1. 初值角度为y轴正方向,则初始degree=90度
  2. 不管当前行走方向如何,向左转转,就是degree+90,向右转就是degree-90,不过要保证当前degree[0,360)这个区间内
  3. 将角度转换成方向向量
  • degree==0时,为x轴正方向,方向向量为(1,0),那么向前走x步,相当于(1,0)*x + (当前坐标)
  • 以此类推,当degree==90度时,方向向量是(0,1)
  • 当degree==180度时,方向向量是(-1,0)
  • 当degree==270度时,方向向量是(0,-1)
  1. 向某个方向移动了x步,就是当前坐标加上x乘以当前角度上的方向向量。考虑到障碍物的情况,在实际移动时,需要每次试探性的移动一步,试探是否和障碍物的集合重合,如果不重合说明前面没有障碍物,向前移动一步,如果重合,说明前面有障碍物,直接跳出当前循环即可

三、AC 代码:

class Solution {
public:
    int robotSim(vector<int> &commands, vector<vector<int>> &obstacles) {
        int degree = 90;
        pair<int, int> currentPos = {0, 0};
        set<pair<int, int>> obstacleSet;
        int ans = 0;
        for (int i = 0; i < obstacles.size(); i++) {
            obstacleSet.insert(make_pair(obstacles[i][0], obstacles[i][1]));
        }
        for (int i = 0; i < commands.size(); i++) {
            if (commands[i] == -1) {
                degree = degree - 90;
            } else if (commands[i] == -2) {
                degree = degree + 90;
            } else {
                pair<int, int> direction = getXY(degree);
                for (int j = 0; j < commands[i]; j++) {
                    int nextX = direction.first + currentPos.first;
                    int nextY = direction.second + currentPos.second;
                    if (obstacleSet.find(make_pair(nextX, nextY)) == obstacleSet.end()) {
                        currentPos = make_pair(nextX, nextY);
                        ans = max(ans, currentPos.first * currentPos.first + currentPos.second * currentPos.second);
                    } else {
                        break;
                    }
                }
            }
            degree = degree < 0 ? degree + 360 : degree;
            degree = degree >= 360 ? degree - 360 : degree;
        }

        return ans;
    }

    /**
     * x:<1,0>
     * y:<0,1>
     * -x:<-1,0>
     * -y:<0,-1>
     */
    pair<int, int> getXY(int degree) {
        switch (degree) {
            case 0:
                return make_pair(1, 0);
            case 90:
                return make_pair(0, 1);
            case 180:
                return make_pair(-1, 0);
            case 270:
                return make_pair(0, -1);
            case 360:
                return make_pair(0, 0);
            default:
                // error
                return make_pair(-2, -2);
        }
    }
};

四、总结:

向量运算比较好理解吧。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看活动详情