874. 模拟行走机器人

874. 模拟行走机器人

审题


以示例2为例,先把题目意思搞明白。
输入: commands = [4, -1, 4, -2, 4], obstacles = [[2,4]]
输出: 机器人所经过的每个坐标点 (x, y) 到原点的欧式距离的平方的最大值。
欧式距离: x 2 + y 2 \sqrt{x^2 + y^2} x2+y2
欧式距离的平方:$ x2+y2 $

如上图所示:
机器人初始位置坐标点(0,0) 初始方向为 向北。

  1. 读取第一个指令为4,沿着当前当前方向“北”,向前走4个单位,停在坐标点9(0,4)
  2. 读取第二个指令为-1,该指令表示“向右转90度”,那么机器人就由原来的“北”右转90度之后方向变为“东”
  3. 读取第三个指令为4,沿着当前方向“东”,向前走4个单位,但是发现坐标点(2,4) 是一个障碍物,不能跨越,只能停留在障碍物前面一个单位,即坐标点(1,4)
  4. 读取第四个指令为-2,该指令表示“向左转90度”,那么机器人就由原来的“东”左转90度之后方向变为“北”
  5. 读取第五个指令为4,沿着当前方向“北”,向前走4个单位,停留在坐标点(1,8)

65怎么得来的? 机器人所经过的这些点中,坐标点(1,8) 计算出的欧式距离的平方最大,为 1 2 + 8 2 = 65 1^2 + 8^2 = 65 12+82=65

解题思路

总体思想: 模拟机器人行走过程,计算每一步坐标点到原点的欧式距离的平方,于保存的最大值比较,实时更小最大值。具体如下:

1.分解机器人行走

k 步,就是朝着一个方向走 k 个1步
怎么朝着某个方向走出一步

  • 方向向北,机器人坐标向上走一步
  • 方向向东,机器人坐标向右走一步
  • 方向向南,机器人坐标向下走一步
  • 方向向西,机器人坐标向上走一步

int direx[] = {0, 1, 0, -1}
int direy[] = {1, 0, -1, 0}
direx[],direy[] 要竖着对齐看

  • 向北,坐标轴上x不动,y+1,即(0,1)
  • 向东,坐标轴上x+1,y不动,即(1,0)
  • 向南,坐标轴上x不动,y-1,即(0,-1)
  • 向西,坐标轴上x-1,y不动,即(-1,0)

(direx[i], direy[i]),加上当前坐标后为 (curx,cury)+(direx[i], direy[i])

2.机器人如何调整方向

direx[]direy[] 的下标 i 代表了当前机器人的方向 \

  • i = 0, 向北
  • i = 1, 向东
  • i = 2, 向南
  • i = 3, 向西

当读取到调整方向的指令时,如

  • “-1”:“向右转90度”,只要当前方向 curdire + 1 就可以得到右转方向
  • “-2”:“向左转90度”,只要当前方向 curdire + 3 就可以得到左转方向 (curdire + 3) % 4,因为不管 curdire 当前是哪个方向,左转都在其左边,在 direx 数组的定义中顺时针数3个就是其左边,所以就是加3。

3.怎么判断是否遇到了障碍物

障碍物有多个,所以需要有一个障碍物坐标点集合
机器人每试图走一个位置,就用此位置于障碍物集合列表李的坐标进行比较,判断是否刚好是障碍物坐标点。

  • 不是,则真正走到这个点,更小机器人坐标点(curx, cury)
  • 是障碍物,那么不走下一步,停留在当前,执行下一条命令

4.实现方法

  • -1、-2 表示左右移动可需要工具指定东来西北,判断左右移动方向从而取得当前的朝向;
  • 每移动一步都需要判断障碍物,所以需要快速寻找,这里可以考虑使用hashmap或者hashset;
  • 每一个朝向的移动就是一个循环,只要遇到障碍物就结束当前循环,每循环一次都比较一次最远距离;
  • 返回最远距离。

参考代码

class Solution {
    public int robotSim(int[] commands, int[][] obstacles) {
        // direction 表示当前朝向,0 1 2 3 表示 北东南西
        int ans = 0, direction = 0, x = 0, y = 0;
        // 每个朝向上的数据变化,比如朝北时取 Direction[0] -> {0, 1}
        // 那么x轴的变化为x+0, y轴变化为y+1
        int[][] Direction = {{0,1}, {1,0}, {0,-1}, {-1,0}};

        HashSet<String> set = new HashSet<>();
        // 将所有障碍物坐标组合成字符串存入set中方便查询
        for (int[] arr : obstacles) set.add(arr[0] + "," + arr[1]);

        for (int com : commands) {
            // 定义下一步的坐标
            int next_x = 0, next_y = 0;
            // 当命令为前进,开始移动
            if (com >= 0) {
                for(int i = 0; i < com; i++) {
                    // 取得下一步的坐标
                    next_x = x + Direction[direction][0];
                    next_y = y + Direction[direction][1];
                    // 若下一步有障碍物,结束当前命令,跳至下一命令
                    if(set.contains(next_x + "," + next_y)) break;
                    // 否则更小坐标于最远距离
                    x = next_x;
                    y = next_y;
                    ans = Math.max(ans, x*x + y*y);
                }
            } else {
                // 改变朝向,-1:向右转90度,-2:向左转90度
                direction = com == -1 ? (direction + 1) % 4 : (direction + 3) % 4;
            }
        }
        return ans;
    }
}

部分图片来源于网络,版权归原作者,侵删。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值