zoukankan      html  css  js  c++  java
  • 机器人冒险

      力扣团队买了一个可编程机器人,机器人初始位置在原点(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
    解释:到达终点后,再碰到障碍物也不影响返回结果。

    限制:

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

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


      这道题目一开始我的思路是模拟机器人的行走过程,然后在机器人每走一步之后判断其是否在障碍点,是否抵达了终点…但我想这样可能会超出时间限制,但我还是想写出来试试,果不其然,超出时间限制!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class :
    def robot(self, command: str, obstacles: List[List[int]], x: int, y: int) -> bool:
    if x == 0 and y == 0:
    return True
    x0 = y0 = 0
    while(True):
    for ch in command:
    if ch == 'U':
    y0 += 1
    else:
    x0 += 1
    for obs in obstacles:

    if obs[0] > x0 or obs[1] > y0:
    continue
    if obs == [x0, y0]:
    return False
    # 抵达终点
    if x0 == x and y0 == y:
    return True

      之后我想着机器人行走路径中的点必然有一种规律,这样题目才可能得以简化,我一开始是想把终点和所有障碍点通过某种方式使之等价于单次循环中机器人可能经过的点,我觉得方向是没错的,但在编程的时候又把问题复杂化了,所以一直没调试出来。
      然后看了题解中大佬们的解答,总结出两种方法。一是我们可以根据command推算出机器人的行走路径,比如command=’URR’,我们可以推算出如下坐标:
    (0,1), (1,1), (2,1)
    (2,2), (3,2), (4,2)
    (4,3), (5,3), (6,3)…以此类推
    从上面我们发现
    (3,2) - (1,1) = (2,1);
    (4,3) - (0,1) = (4,2);
    (6,3) - (2,1) = (4,2);
      上面式子的结果都是完整执行一次command命令之后坐标点的倍数。因此判断某个点p是否在行走路径上的条件是:
    (pos[0] == p[0] and pos[1] == p[1]) or (pos[1] != p[0] and (p[0]-pos[0])/(p[1]-pos[1]) == divpos[0]/divpos[1])
      其中pos是单次循环机器人所走过的坐标中的一点,divpos是完整执行一次command命令之后的坐标点。
      而机器人能完好到达终点的条件是:(1)终点坐标在行动轨迹上;(2)在到达终点之前没有障碍点在行动轨迹上

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    class :
    def robot(self, command: str, obstacles: List[List[int]], x: int, y: int) -> bool:
    if x == 0 and y == 0:
    return True
    ori, oripos = [0, 0], []
    for ch in command:
    if ch == 'R':
    ori[0] += 1
    else:
    ori[1] += 1
    oripos.append(ori[:])
    divpos = oripos[-1]
    # 判断终点是否在行走路径上
    for pos in oripos:
    if (pos[0] == x and pos[1] == y) or (pos[1] != y and (x-pos[0])/(y-pos[1大专栏  机器人冒险span>]) == divpos[0]/divpos[1]):
    break
    else:
    return False
    # 判断障碍物是否在行走路径上
    for obs in obstacles:
    # 障碍物超出终点
    if obs[0] > x or obs[1] > y:
    continue
    for pos in oripos: # 判断某个障碍物是否在行走路径上
    if (pos[0] == obs[0] and pos[1] == obs[1]) or (pos[1] != obs[1] and (obs[0]-pos[0])/(obs[1]-pos[1]) == divpos[0]/divpos[1]):
    return False
    return True

      第二种解法是我们可以通过上面所讲的规律找到接近终点和障碍点的某个点,以这个点为起始我们可以在单次循环中判断终点和障碍点是否在行走路径上。比如对于command=’URR’,在如下坐标点中:
    (0,1),(1,1),(2,1)
    (2,2),(3,2),(4,2)
    (4,3),(5,3),(6,3)
      (2,1)是接近(2,2),(3,2),(4,2)三个点的坐标,(4,2)是接近(4,3),(5,3),(6,3)三个点的坐标,也就是(2,1),(4,2)都是(2,1)的倍数,具体求解方法请看代码中get_floor_xy()函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    class :
    def __init__(self):
    self.unit_x = 0
    self.unit_y = 0
    # command指令单循环一次
    def init_unit(self, command):
    for ch in command:
    if ch == 'R':
    self.unit_x += 1
    else:
    self.unit_y += 1
    # 获得在行走路径中最接近[x, y]的路径点
    def get_floor_xy(self, x, y):
    # command至少有一个U和R,所以不必担心除数为0
    min_rate = min(x // self.unit_x, y // self.unit_y)
    return min_rate * self.unit_x, min_rate * self.unit_y
    # 判断某个点是否在行走路径上
    def on_the_way(self, command, x1, y1):
    x0, y0 = self.get_floor_xy(x1, y1)
    if x0 == x1 and y0 == y1:
    return True
    # 判断单次循环下,是否途径目标点
    for ch in command:
    if ch == 'R':
    x0 += 1
    else:
    y0 += 1
    if x0 == x1 and y0 == y1:
    return True
    else:
    return False
    def robot(self, command: str, obstacles: List[List[int]], x: int, y: int) -> bool:
    self.init_unit(command)
    # 判断终点是否在行走路径上
    if not self.on_the_way(command, x, y):
    return False
    # 判断障碍点是否在行走路径上
    for obs in obstacles:
    # 障碍点是否超出了范围
    if obs[0] > x or obs[1] > y:
    continue
    # 障碍点是否在路径上
    if self.on_the_way(command, obs[0], obs[1]):
    return False
    return True
  • 相关阅读:
    android: 在android studio中使用retrolambda的步骤
    Shiro基础知识03----shiro授权(编程式授权),Permission详解,授权流程(zz)
    [Android] 关于Android的问号?和@符号的用法
    20170506 《摔跤吧,爸爸》观影笔记
    Android关于log日志,华为不输出log.v,log.d(zz)
    阅读日志:协鑫一年的多晶硅料产能能够生产做少装机容量的组件?
    《周鸿祎自述》读书笔记
    使用promise 和 generator来管理工作流
    读书笔记,《刻意练习》,第三章,心理表征
    读书笔记,《刻意练习》,第四章,黄金标准
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12366770.html
Copyright © 2011-2022 走看看