理解本题的题意很关键,机器人在(0,0)点开始行走,如果(0,0)点有障碍怎么办,这种情况是不管它,开始下一步行走,一旦机器人离开(0,0)点,这个点的障碍物才生效,后面如果回到此点则不能跨过此障碍。也就是说我们需要先走一步,再去判断这一步是否有效,有效则更新坐标,否则原地不动,继续下一次动作。至于右转和左转实际就是改变机器人的朝向,起初机器人向北,右转则朝向东,左转则朝向西。不同的朝向,意味着向前一步改变的坐标形式不一样,如果朝北,则x不动,y递增;如果朝南,则x不动,y递减;如果朝西,则x递减,y不动;如果朝东,则x递增,y不动;也就是在每次实施除了左转右转的动作(调整朝向)之外的移动操作时,需要知道机器人的朝向。知道了朝向就往前走呗,遇到了前方障碍物则不要往前,结束此次动作,开始下一次动作。
难点是怎么确定朝向,有个笨办法是用一个整数表示此方向,1代表北方,-1代表南方,2代表东方,-2代表西方。当方向标识的绝对值等于1时,前进动作改变的是y坐标;当方向标识的绝对值等于2时,前进动作改变的是x坐标。当方向标识大于0时,每次向前前进1位;当方向标识小于0时,每次后退1位;还有一个问题是,确定朝向,我们可以把分别在东西南北时右转左转的方向写好,如果每次动作是转动(值<0)时直接调用方向选择常量确定本次转动后的朝向。这就叫方法一吧。
方法二,优化方向的表示,如果用坐标来表示方向不仅可以很好的确定方向之间的关系,而且还能确定此方向上的增量。考虑[0,1],[1,0],[0,-1],[-1,0]分别代表北、东,南,西。可以看到每个坐标的左边就是它的左转方向,右边的就是它的右边方向,也就是说,给一个方向i(方向向量的索引),则左转的方向是i-1,右转的方向是i+1。等等,那两头呢,开始的位置不能减1,末端的位置不能加1。把首和尾连接器起来就好了,因此要进行取余操作,长度为4。当然了(0-1)%4没意义,因此改写成((0-1)+4)%4,即左转为(i+3)%4,这样对中间位置和起始位置都适用。方向确定好了。那坐标增量呢,注意到某一方向上行进一步的增量恰好就是该方向的坐标。以北为例,y方向增量是1,x方向增量是0,也就是(0,1)。这种方法可以大大减少代码量。
但是这种方法有冗余操作,在不需要更新x或者y时还是会进行无用的赋值。
方法二:
class Solution {
public:
int robotSim(vector<int>& commands, vector<vector<int>>& obstacles) {
vector<pair<int,int>> dire={{0,1},{1,0},{0,-1},{-1,0}};
set<pair<int,int>> ob;
int i=0,x=0,y=0,maxdis=0;
for(vector<int> vi:obstacles){
ob.insert(make_pair(vi[0],vi[1]));
}
for(int cd:commands){
if(cd==-2){//左转
i=(i+3)%4;
}else if(cd==-1){//右转
i=(i+1)%4;
}else{//在某一个方向上对x或者对y更改
while(cd){
int dx=x+dire[i].first;
int dy=y+dire[i].second;
if(ob.find(make_pair(dx,dy))==ob.end()){//没有障碍物则更新x和y
x=dx;
y=dy;
maxdis=max(maxdis,x*x+y*y);
}else{
break;
}
--cd;
}
}
}
return maxdis;
}
};
方法一 (笨办法)
class Solution {
public:
int robotSim(vector<int>& commands, vector<vector<int>>& obstacles) {
int flag=1; // 1向北,2向东,-1向南,-2向西
//0左转变3,0右转变1
map<pair<int, int>,int> hash;
set<pair<int, int>> ob;
// {1,-2}表示北左转,re表示转后的朝向
vector<pair<int,int>> vep={{1,-2},{1,-1},{2,-2},{2,-1},{-2,-2},{-2,-1},{-1,-2},{-1,-1}};
vector<int>re={-2,2,1,-1,-1,1,2,-2};
for(int i=0;i<re.size();i++){
hash[vep[i]]=re[i];
}
for(int i=0;i<obstacles.size();i++)
{
ob.insert(make_pair(obstacles[i][0],obstacles[i][1]));
}
int x=0,y=0;
int step;
int distance=0;
for(int step:commands)
{
int sym=flag>0?1:-1;
if(step>0){
if(abs(flag)==1){
while(step>0){
int ds=y+sym;
if(ob.find(make_pair(x,ds))==ob.end()){
y=ds;
distance=max(distance,x*x+y*y);
}else{
break;
}
--step;
}
}else{
while(step>0){
int ds=x+sym;
if(ob.find(make_pair(ds,y))==ob.end()){
x=ds;
distance=max(distance,x*x+y*y);
}else{
break;
}
--step
}
}
}else{//改变方向
flag= hash[make_pair(flag,step)];
}
}
return distance;
}
};
674

被折叠的 条评论
为什么被折叠?



