题目:
力扣团队买了一个可编程机器人,机器人初始位置在原点(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]不为原点或者终点
解析
参考博文: https://blog.csdn.net/happyeveryday62/article/details/101377782#comments
首先判断在没有障碍物的情况下,机器人能否到达终点,如果不能直接返回false;
接下来,判断机器人能否到达障碍物的位置,如果能直接返回false;
核心部分就是判断能否到达某个位置.
实现时先判断能否刚好循环整数个指令,然后判断指令子串,更加方便.
tip:
范围for语句,遍历给定序列中的每个元素,是对单个元素的访问.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int k;
vector<vector<int>> vec(2);//vec是vector类型,它存储的值的类型为vector<int>
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
{
cin>>k;
vec[i].push_back(k);
}
for(auto b:vec)//b是vector<int>类型,是把vec的内容单个赋值给b
{
cout<<b[0]<<" ";
cout<<b[1]<<endl;
}
return 0;
}
//输入:2 9 6 5
//输出:
//2 9
//6 5
solution:
class Solution {
public:
int step_u=0,step_r=0;
bool canReach(string command,int x,int y)
{
int step=min(x/step_r,y/step_u);
int now_x = step*step_r;
int now_y = step*step_u;
if(now_x == x&&now_y == y) return true;
else
{
for(int i =0;i<(int)command.size();i++)
{
if(command[i]=='U')
{
++now_y;
if(now_x == x&&now_y == y) return true;
}
else
{
++now_x;
if(now_x == x&&now_y == y) return true;
}
}
return false;
}
}
bool robot(string command, vector<vector<int>>& obstacles, int x, int y)
{
//统计一个完整的指令中在各个方向有多少个移动步骤
for(char st:command)
{
if(st == 'U')
++step_u;
else
++step_r;
}
if(canReach(command,x,y))//判断没有障碍时能否到达终点
{
for(int i=0;i<(int)obstacles.size();i++)//判断能否到达障碍物的位置
{
if((obstacles[i][0]<=x&&obstacles[i][1]<y)||(obstacles[i][0]<x&&obstacles[i][1]<=y))
if(canReach(command,obstacles[i][0],obstacles[i][1]))
return false;
}
return true;
}
else
return false;
}
};
方案二:
很巧妙,但是有待再分析欣赏!!!
class Solution {
public:
bool robot(string command, vector<vector<int>>& obstacles, int x, int y) {
int a=0,b=0,u=0,v=0;
for(auto i:command)if(i=='R')a++;//统计指令中up与right的次数
else b++;
bool c=0;
for(auto i:command)//逐步执行指令(这里太妙了)
{
for(auto j:obstacles)if(j[0]<=x&&j[1]<=y&&(j[0]-u)%a==0&&(j[1]-v)%b==0&&(j[0]-u)/a==(j[1]-v)/b)return 0;//若执行部分指令,可到达原点与终点间的某个障碍物,则直接返回false
if((x-u)%a==0&&(y-v)%b==0&&(x-u)/a==(y-v)/b)c=1;//可以到达终点,更新标记
if(i=='R')u++;//统计已执行的指令中的up与right的次数
else v++;
}
return c;
}
};
方案三
我自己的写法,会超时,很感谢网友的帮忙才得以让这个超时的程序跑通,不然真心不知道跪在哪里…虽然答案不正确,但是有很多值得学习的小知识点,所以记录在次此.
class Solution {
public:
bool robot(string command, vector<vector<int>>& obstacles, int x, int y) {
int xx=0;//起始位置,表示行
int yy=0;
int n = command.size();
map<pair<int,int>,bool> mark;//表示是否有障碍物
//这里的障碍物不能用数组表示,首先不能用vector因为无法自动初始化所以不能下标访问;其次,数组的范围是到
//1e9,开数组的话内存不够大
for(auto b:obstacles)
{
mark[make_pair(b[0],b[1])] = true;
}
for(int i=0;i<=n;i++)
{
if(i==n)
i=0;
if(command[i] == 'U')
yy++;
else
{
xx++;
}
//cout<<xx<<" "<<yy<<endl;
if(xx>x || yy>y)
break;
if(mark[make_pair(xx,yy)] == 1)
break;
if(xx==x && yy==y)
break;
}
if(xx==x && yy==y)
return true;
else
return false;
}
};