问题描述:一个机器人现在处于(0,0)的位置,面朝北方,机器人会受到下面的指令:
(1)-2:向左转90度
(2)-1:向右转90度
(3)1=<x<=9的整数:前进x步,路上会有障碍物,遇到障碍物不能前进。给定指令集合和障碍物的位置,求机器人能够到达的最远位置的平方。
分析:题目本身比较简单,我们按照给定的要求操作,如果是前进先判断是否遇到障碍物,每次只走一步。但是写程序的时候比较麻烦的是转向,每次结果需要根据当前的方向和命令来算出执行命令后的方向。所以想找到一种一致的转向方法。矩阵可以完成这个操作,假设我们用21的矩阵表示点,22的矩阵作为转向矩阵(这样最后的结果依然表示点)
转向矩阵计算:
X=[x1x2x3x4]X=
\begin{bmatrix}
x_1 &x_2 \\
x_3 &x_4 \\
\end{bmatrix}
X=[x1x3x2x4]
原来的向量
m=[m1m2]m=\begin{bmatrix}
m_1 \\
m_2 \\
\end{bmatrix}m=[m1m2]
通过转向后的垂直我们得到mX∗m=[0,0]TmX*m=[0,0]^TmX∗m=[0,0]T(这里*表示点乘)
最终得到x1=x4=0,x2=−x3x_1=x_4=0,x_2=-x_3x1=x4=0,x2=−x3,当x_2>0时是向右转,反之向左转
这样程序就完成了。
时间复杂度分析:每次只走一步,时间复杂度与移动格子数成正比。也可以判断障碍物是否在行进路经线段上来直接判断(点在直线上加上线段两端的限制),这样时间复杂度大约是跟指令数目一致O(n)
public int robotSim(int[] commands, int[][] obstacles) {
int dire_x = 0;
int dire_y = 1;
int x=0,y = 0;
int maxdisq = 0;
Set<String> set = new HashSet<String>();
for(int [] ts : obstacles) {
set.add(ts[0]+","+ts[1]);
}
for(int i:commands) {
if(i==-2) {
int tmp = dire_x;简化矩阵运算
dire_x = -dire_y;
dire_y = tmp*1;
}
if(i==-1) {
int tmp = dire_x;//简化了矩阵运算
dire_x = dire_y;
dire_y = -tmp;
}
else if(i>=1&&i<=9) {
for(int j = 0;j<i;j++) {
int tmpx = x+dire_x;
int tmpy = y+dire_y;
if(set.contains(tmpx+","+tmpy)) {
break;
}
else {
x=tmpx;
y=tmpy;
int disquare = x*x+y*y;
maxdisq = disquare>maxdisq?disquare:maxdisq;
}
}
}
}
return maxdisq;
}