LeetCode874:機器人路徑模擬
題目:
A robot on an infinite grid starts at point (0, 0) and faces north. The robot can receive one of three possible types of commands:
- -2: turn left 90 degrees
-1
: turn right 90 degrees1 <= x <= 9
: move forwardx
units
Some of the grid squares are obstacles.
The i
-th obstacle is at grid point (obstacles[i][0], obstacles[i][1])
If the robot would try to move onto them, the robot stays on the previous grid square instead (but still continues following the rest of the route.)
Return the square of the maximum Euclidean distance that the robot will be from the origin.
題目大意是說有一個機器人初始時在座標(0,0)位置,在無限大的平面中行走,初始時方向正北,給定一系列命令,要求尋找機器人在某個點離遠點最遠距離的平方。
解題思路:
這道題在leetcode難度是simple,也就是簡單,實際上這道題思路簡單,但是想寫出完整的程式碼還是不容易的。首先,我們需要定義方向,這個可以任意定義,我是這麼做的,宣告一個變數direction,它的取值集合為{0,1,2,3},分別表示正北,正東,正南,正西四個方向,再定義兩個變數currentX,currentY,表示當前機器人所在的座標,另外需要考慮的是有障礙物的情況,每一個障礙物的座標已經儲存在obstacles陣列中,接下來以一個具體的案例為例解釋應該如何做:
假設某一次機器人在(2,4)這個位置,此時direction=3,表示機器人面朝正西,如果commands[i]<0,表示只需要改變方向,也就是修改direction的值。
commands[i]=-1,表示向右轉,direction=(direction+1)%4,這裡取模的主要考慮到direction=3時,向右轉到正北,direction應該等於零;
commands[i]=-2,表示向左轉,direction=(direction+3)%4,向左轉一次可以認為是向右轉3次。
commands[i]=4.表示向前進4格,如果此時direction=3,表示應該向正西方向前進4格,我們的第一個問題是,能向前進這麼多嗎?
能不能要看從當前的座標,然後向西進4格這條路徑上是否有障礙物,我們知道,此時機器人在(2,4)位置上,向西前進4格如果沒有障礙物,應該到達(-2,4)的位置,也就是說,向西前進y座標不變,此時,我們應該遍歷障礙物陣列,看看是否有障礙物落在這條線上,遍歷的時候obstacles[j][1]=4&&obstacles[j][0]>=-2&&obstacles[j][0]<2,就表示該路徑中存在一個障礙物,這裡要注意,為什麼-2那個地方要取等號,而2可以不取等號,假設obstacles[j][0]=-2,表示剛好目標位置(-2,4)是一個障礙物,按照題意,機器人不能到達障礙物,只能到達障礙物的前一位置,因此,取等號的時候也要考慮進去。假設obstacles[j][0]=2,這實際上是不存在的,因為機器人不可能處在一個障礙物上,只要我們正確更新機器人的行走路徑。另外還需要考慮一個問題,就是當這條路徑上有不止一個障礙物應該怎麼取捨,比如從(2,4)到(-2,4)這條路上,如果有(-1,4)、(0,4)兩個障礙物,應該怎麼辦呢,按照題目意思,應該去裡起點(2,4)最近的那個障礙物(0,4)的前一個位置,也就是機器人此時只能走一步,走到(1,4)位置。
最後需要思考一個問題,什麼時候需要計算距離,答案是每當機器人走到一個新的座標,需要考慮下一步應該怎麼走的時候,就應該計算一次距離,然後更新結果。
java程式碼如下:
public int[]getDirection(int direction,int currentX,int currentY,int[][]obstacles,int step){
//該函式的含義是,給定direction,取值在0,1,2,3,當前位置座標是(currentX,currentY),需要向direction方向前進
//step步,當然,所有的障礙物都在obstacles中儲存
int[]result=new int[2]; // 該變數含義是在這種情況下最終返回的結果座標是(result[0],result[1])
int i,aimX=0,aimY=0;// 目標位置座標是(aimX,aimY)
switch(direction){ // 根據direction的方向前進
case 0: // 表示應該往正北方向前進step
aimX=currentX;// 往正北方向前進x座標是不變的
aimY=currentY+step; // 往正北方向前進step步,那麼aimY應該在currentY的基礎上加上step,
//如果此時這條路徑上沒有障礙物,那麼aimY得到正確更新
for(i=0;i<obstacles.length;i++){
if(obstacles[i][0]==aimX&&obstacles[i][1]>currentY&&obstacles[i][1]<=aimY)
aimY=obstacles[i][1]-1;
}
// for迴圈中遍歷所有障礙物,如果發現在這條路徑上存在障礙物,那麼應該在障礙物的前一個點停下來
break;
case 1:
aimX=currentX+step;
aimY=currentY;
for(i=0;i<obstacles.length;i++){
if(obstacles[i][1]==aimY&&obstacles[i][0]>currentX&&obstacles[i][0]<=aimX)
aimX=obstacles[i][0]-1;
}
break;
case 2:
aimX=currentX;
aimY=currentY-step;
for(i=0;i<obstacles.length;i++){
if(obstacles[i][0]==aimX&&obstacles[i][1]<currentY&&obstacles[i][1]>=aimY)
aimY=obstacles[i][1]+1;
}
break;
default:
aimY=currentY;
aimX=currentX-step;
for(i=0;i<obstacles.length;i++)
if(obstacles[i][1]==aimY&&obstacles[i][0]<currentX&&obstacles[i][0]>=aimX)
aimX=obstacles[i][0]+1;
}
result[0]=aimX;
result[1]=aimY;
return result;
}
public int robotSim(int[] commands, int[][] obstacles) {
int direction=0,currentX=0,currentY=0,i,result=0,tempResult=0;
// direction表示機器人當前的方向,(currentX,currentY)表示機器人當前所在的座標
// result表示最終離原點最長距離的平方,tempResult表示當前座標離遠點的距離的平方
if(commands==null||commands.length<=0)
return result;
for(i=0;i<commands.length;i++){
if(commands[i]>0){
int []directionIndex=getDirection(direction, currentX, currentY, obstacles, commands[i]);
currentX=directionIndex[0];
currentY=directionIndex[1];
tempResult=currentX*currentX+currentY*currentY;
result=tempResult>result?tempResult:result;
}
else{ // commands[i]<0表示只需要改變方向
if(commands[i]==-1) // commands[i]=-1,表示右轉,方向+1
direction=(direction+1)%4;
else
direction=(direction+4-1)%4;
}
}
System.out.println(result);
return result;
}