LCP 03 机器人大冒险(分析-计算运动周期)

1. 问题描述:

力扣团队买了一个可编程机器人,机器人初始位置在原点(0, 0)。小伙伴事先给机器人输入一串指令command,机器人就会无限循环这条指令的步骤进行移动。指令有两种:
U: 向y轴正方向移动一格
R: 向x轴正方向移动一格。

不幸的是,在 xy 平面上还有一些障碍物,他们的坐标用obstacles表示。机器人一旦碰到障碍物就会被损毁。给定终点坐标(x, y),返回机器人能否完好地到达终点。如果能,返回true;否则返回false。

示例 1:

输入:command = "URR", obstacles = [], x = 3, y = 2
输出:true
解释:U(0, 1) -> R(1, 1) -> R(2, 1) -> U(2, 2) -> R(3, 2)。

示例 2:

输入:command = "URR", obstacles = [[2, 2]], x = 3, y = 2
输出:false
解释:机器人在到达终点前会碰到(2, 2)的障碍物。

示例 3:

输入:command = "URR", obstacles = [[4, 2]], x = 3, y = 2
输出:true
解释:到达终点后,再碰到障碍物也不影响返回结果。

限制:

2 <= command的长度 <= 1000
command由U,R构成,且至少有一个U,至少有一个R
0 <= x <= 1e9, 0 <= y <= 1e9
0 <= obstacles的长度 <= 1000
obstacles[i]不为原点或者终点

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/programmable-robot

2. 思路分析:

① 首先最容易想到的是模拟机器人运动过程的做法,运动过程中判断当前的位置是否碰到了障碍物,如果碰到了障碍物那么直接return False,没有则继续移动但是很遗憾,模拟运动轨迹的做法提交上去超时了,题目的测试用例中有一些非常大的数据所以会超时

② 除了使用模拟的方法之外,还可以这样想,因为每一次都是都是使用同样的指令进行移动,所以我们可以计算从位置(0, 0)出发一直到目标位置可以经过多少个循环到达目标位置(x, y)的最近位置,也就是不超过(x, y)的最近位置,经过这样计算的话说明我可以通过这样多次的周期运动到达(x1, y1)位置,下一次还是这样运动(不满一个周期),所以实际上是相当于是判断第一次机器人的运动轨迹是否可以到达目标位置,所以最终转化为第一次的运动轨迹是否存在(x0, y0)坐标能够到达目标位置。具体的做法是我们需要记录下第一次的运动的轨迹,也就是每一次运动的(x0, y0)坐标,因为使用的是python语言所以使用字典记录这些位置即可,字典的键为元组类型,可以表示(x,y)位置。我们可以计算出第一次运动之后的坐标,这个坐标表示一个周期,然后通过计算多少个周期将目标位置(x, y)映射到第一次运动的轨迹中最终判断映射到第一次运动轨迹的字典中是否有这个坐标如果存在说明是可以从(0, 0)这个位置到达(x,y)位置的

③ 第二步是判断在运动过程中是否会碰到障碍物,其实与判断是否可以到达目标位置的方法是一样的,也是将当前遍历的障碍物位置映射到第一次的运动轨迹中看字典中是否存在如果存在说明在运动过程中碰到了障碍物,返回False,并且需要注意的是需要判断一下障碍物的位置需要在目标位置范围之内碰到才是有效的,因为到达目标位置之后再碰到障碍物是没有用的

3. 代码如下:

模拟:

import collections
from typing import List


class Solution:
    def robot(self, command: str, obstacles: List[List[int]], x: int, y: int) -> bool:
        x0, y0 = 0, 0
        index = 0
        dic = collections.defaultdict(int)
        # 使用元组来表示障碍物的位置
        for cur in obstacles:
            dic[(cur[0], cur[1])] += 1
        while (x0 < x or y0 < y) and (x0, y0) not in dic:
            if command[index] == "U":
                y0 += 1
            else:
                x0 += 1
            index = (index + 1) % len(command)
        return x0 == x and y0 == y

计算周期:

import collections
from typing import List


class Solution:
    def robot(self, command: str, obstacles: List[List[int]], x: int, y: int) -> bool:
        dic = collections.defaultdict(tuple)
        # 起始坐标
        x0, y0 = 0, 0
        dic[(0, 0)] = 1
        # 记录下第一次的运动轨迹
        for c in command:
            if c == "U":
                y0 += 1
            else:
                x0 += 1
            dic[(x0, y0)] = 1
        circle = min(x // x0, y // y0)
        # 第一次轨迹中没有存在这样的点可以到达目标位置
        if (x - circle * x0, y - circle * y0) not in dic: return False
        # 判断目标点是否是障碍物的位置, 其实与判断是否可以到达目标位置的方法是一样的
        for pos in obstacles:
            xt, yt = pos[0], pos[1]
            circle = min(xt // x0, yt // y0)
            # 障碍物必须在目标范围之内
            if (xt - circle * x0, yt - circle * y0) in dic and xt <= x and yt <= y:
                return False
        return True

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值