leetcode 力扣 1414 网格中的最短路径题解 算法题.docx
《leetcode 力扣 1414 网格中的最短路径题解 算法题.docx》由会员分享,可在线阅读,更多相关《leetcode 力扣 1414 网格中的最短路径题解 算法题.docx(14页珍藏版)》请在冰豆网上搜索。
![leetcode 力扣 1414 网格中的最短路径题解 算法题.docx](https://file1.bdocx.com/fileroot1/2023-1/21/431ab3fe-3579-45cf-9815-566135e46d78/431ab3fe-3579-45cf-9815-566135e46d781.gif)
leetcode力扣1414网格中的最短路径题解算法题
题目:
网格中的最短路径
给你一个 m*n 的网格,其中每个单元格不是 0(空)就是 1(障碍物)。
每一步,您都可以在空白单元格中上、下、左、右移动。
如果您最多可以消除k个障碍物,请找出从左上角(0,0)到右下角(m-1,n-1)的最短路径,并返回通过该路径所需的步数。
如果找不到这样的路径,则返回-1。
示例1:
输入:
grid=
[[0,0,0],
[1,1,0],
[0,0,0],
[0,1,1],
[0,0,0]],
k=1
输出:
6
解释:
不消除任何障碍的最短路径是10。
消除位置(3,2)处的障碍后,最短路径是6。
该路径是(0,0)->(0,1)->(0,2)->(1,2)->(2,2)->(3,2)->(4,2).
示例2:
输入:
grid=
[[0,1,1],
[1,1,1],
[1,0,0]],
k=1
输出:
-1
解释:
我们至少需要消除两个障碍才能找到这样的路径。
提示:
•grid.length ==m
•grid[0].length ==n
•1<=m,n<=40
•1<=k<=m*n
•grid[i][j]==0or1
•grid[0][0]==grid[m-1][n-1]==0
语言:
C++
structNagato{
intx,y;
intrest;
Nagato(int_x,int_y,int_r):
x(_x),y(_y),rest(_r){}
};
classSolution{
private:
staticconstexprintdirs[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
public:
intshortestPath(vector>&grid,intk){
intm=grid.size(),n=grid[0].size();
if(m==1&&n==1){
return0;
}
k=min(k,m+n-3);
boolvisited[m][n][k+1];
memset(visited,false,sizeof(visited));
queueq;
q.emplace(0,0,k);
visited[0][0][k]=true;
for(intstep=1;q.size()>0;++step){
intcnt=q.size();
for(int_=0;_Nagatocur=q.front();
q.pop();
for(inti=0;i<4;++i){
intnx=cur.x+dirs[i][0];
intny=cur.y+dirs[i][1];
if(nx>=0&&nx=0&&nyif(grid[nx][ny]==0&&!
visited[nx][ny][cur.rest]){
if(nx==m-1&&ny==n-1){
returnstep;
}
q.emplace(nx,ny,cur.rest);
visited[nx][ny][cur.rest]=true;
}
elseif(grid[nx][ny]==1&&cur.rest>0&&!
visited[nx][ny][cur.rest-1]){
q.emplace(nx,ny,cur.rest-1);
visited[nx][ny][cur.rest-1]=true;
}
}
}
}
}
return-1;
}
};
语言:
Python
classSolution:
defshortestPath(self,grid:
List[List[int]],k:
int)->int:
m,n=len(grid),len(grid[0])
ifm==1andn==1:
return0
k=min(k,m+n-3)
visited=set([(0,0,k)])
q=collections.deque([(0,0,k)])
step=0
whilelen(q)>0:
step+=1
cnt=len(q)
for_inrange(cnt):
x,y,rest=q.popleft()
fordx,dyin[(-1,0),(1,0),(0,-1),(0,1)]:
nx,ny=x+dx,y+dy
if0<=nxifgrid[nx][ny]==0and(nx,ny,rest)notinvisited:
ifnx==m-1andny==n-1:
returnstep
q.append((nx,ny,rest))
visited.add((nx,ny,rest))
elifgrid[nx][ny]==1andrest>0and(nx,ny,rest-1)notinvisited:
q.append((nx,ny,rest-1))
visited.add((nx,ny,rest-1))
return-1
语言:
java
classSolution{
privateint[][]dir=newint[][]{{0,1},{0,-1},{1,0},{-1,0}};
publicintshortestPath(int[][]grid,intk){
intm=grid.length;
intn=grid[0].length;
boolean[][][]visited=newboolean[m][n][k+1];
Queuequeue=newLinkedList<>();
queue.add(newPoint(0,0,0));
//**核心逻辑**:
访问记录二维扩展为三维
visited[0][0][0]=true;
intdistance=0;
while(!
queue.isEmpty()){
distance++;
intsize=queue.size();
for(inti=0;iPointpoint=queue.poll();
intx=point.x;
inty=point.y;
intz=point.z;
//找到障碍物
if(x==m-1&&y==n-1){
returndistance-1;
}
//4个方向移动
for(intj=0;j<4;j++){
intnewX=x+dir[j][0];
intnewY=y+dir[j][1];
intnewZ=z;
if(newX<0||newX>=m||newY<0||newY>=n){
continue;
}
//**核心逻辑**:
有障碍物要对其进行处理,计算是否还能消除障碍物
if(grid[newX][newY]==1){
//没有消除k个障碍物,可以继续消除
if(znewZ=z+1;
}else{
//已经消除k个障碍物
continue;
}
}
if(!
visited[newX][newY][newZ]){
queue.add(newPoint(newX,newY,newZ));
visited[newX][newY][newZ]=true;
}
}
}
}
return-1;
}
classPoint{
intx;
inty;
intz;
publicPoint(intx,inty,intz){
this.x=x;
this.y=y;
this.z=z;
}
}
}
语言:
php
classSolution{
private$arr=array(
array(-1,0),
array(0,-1),
array(1,0),
array(0,1),
);
/**
*@paramInteger[][]$grid
*@paramInteger$k
*@returnInteger
*/
functionshortestPath($grid,$k){
if(count($grid)==1&&count($grid[0])==1){
return0;
}
$visited=array();
$visited['0_0_'.$k]=1;
$stack=array(
array(0,0,$k)
);
$step=0;
while(!
empty($stack)){
$step++;
//var_dump($step);
//var_dump(count($stack));
$stack_add=array();
while(!
empty($stack)){
list($i,$j,$k)=array_pop($stack);
foreach($this->arras$v){
$new_i=$i+$v[0];
$new_j=$j+$v[1];
$new_k=$k;
if($grid[$new_i][$new_j]==1){
$new_k--;
}
if($new_i<0||$new_j<0||$new_k<0
||$new_i>count($grid)-1||$new_j>count($grid[0])-1
||isset($visited[$new_i.'_'.$new_j.'_'.$new_k])
){
continue;
}
if($new_i==count($grid)-1&&$new_j==count($grid[0])-1){
return$step;
}
$visited[$new_i.'_'.$new_j.'_'.$new_k]=1;
$stack_add[]=array($new_i,$new_j,$new_k);
}
}
$stack=$stack_add;
}
return-1;
}
}
语言:
golang
varrN,cNint
funcshortestPath(grid[][]int,kint)int{
rN,cN=len(grid),len(grid[0])
ifrN==1&&cN==1{
return0
}
returnbfs1(grid,k)
}
funcbfs1(grid[][]int,kint)int{
dir:
=[][]int{{0,1},{0,-1},{1,0},{-1,0}}
save:
=make(map[int]map[int]int,rN*cN)
fori:
=0;isave[i]=make(map[int]int)
}
firsBlocks:
=make([]int,rN*cN)
queue:
=make([][]int,0,rN*cN)
queue=append(queue,[]int{0,0})
steps:
=0
forlen(queue)>0{
preLen:
=len(queue)
steps++
ifsteps>rN*cN-1{
break
}
visit:
=make([]int,rN*cN)
//fmt.Println(steps,"---",queue)
forj:
=0;jsr,sc:
=queue[0][0],queue[0][1]
queue=queue[1:
]
visit[sr*cN+sc]=1
fori:
=0;i<4;i++{
r,c:
=sr+dir[i][0],sc+dir[i][1]
ifr<0||r>=rN||c<0||c>=cN{
continue
}
ifr==rN-1&&c==cN-1{//终点
returnsteps
}
idx,preIdx:
=r*cN+c,sr*cN+sc
blocks:
=save[preIdx][steps-1]+grid[r][c]
ifblocks>k{
continue
}
iffirsBlocks[idx]==0{
firsBlocks[blocks]=blocks
}elseifblocks>firsBlocks[blocks]{
continue
}
if_,ok:
=save[idx][steps];!
ok{
save[idx][steps]=blocks
}else{//同一层的扩展节点,相同
ifblockssave[idx][steps]=blocks
}
}
ifvisit[idx]==0{
visit[idx]=1
queue=append(queue,[]int{r,c})
}
}
}
}
return-1
}
语言:
golang
vargridData*[][]int
vardirect=[][]int{{1,0},{0,1},{-1,0},{0,-1}}
varhead,tail*BfsEle
varwidth,height,maxClearint
varflagMapmap[int]bool//访问标记
varbestStep[40][40]int16//最优子结构记录
typeBfsElestruct{
row,col,k,stepint
next*BfsEle
}
funcaddEle(){
for_,nowDirect:
=rangedirect{
newRow:
=head.row+nowDirect[0]
newCol:
=head.col+nowDirect[1]
ifnewRow<0||newRow==height||newCol<0||newCol==width||flagMap[head.k*10000+newRow*100+newCol]{
continue
}
newEle:
=BfsEle{newRow,newCol,-1,head.step+1,nil}
if(*gridData)[newRow][newCol]==0{
newEle.k=head.k
}elseifhead.k+1<=maxClear{
newEle.k=head.k+1
}
ifnewEle.k!
=-1&&bestStep[newRow][newCol]>int16(newEle.k){//有效则追加,无效则不动
bestStep[newRow][newCol]=int16(newEle.k)
tail.next=&newEle
tail=tail.next
flagMap[newEle.k*10000+newRow*100+newCol]=true
}
}
}
funcshortestPath(grid[][]int,kint)int{
height=len(grid)
width=len(grid[0])
gridData=&grid
flagMap=make(map[int]bool)
fori:
=0;iforj:
=0;jbestStep[i][j]=1600
}
}
flagMap[0]=true
bestStep[0][0]=0
head=&BfsEle{0,0,0,0,nil}
tail=head
maxClear=k
forhead!
=nil{
ifhead.col==width-1&&head.row==height-1{
returnhead.step
}
addEle()
head=head.next
}
return-1
}
语言:
javascript
varshortestPath=function(grid,k){
constdirections=[[1,0],[0,1],[-1,0],[0,-1]];
constheight=grid.length;
constwidth=grid[0].length;
constdp=Array(height).fill().map(_=>Array(width).fill().map(_=>Array(k+1).fill(Infinity)));
dp[0][0][0]=0;
constqueue=[[0,0]];
while(queue.length>0){
const[x,y]=queue.shift();
conststatus=dp[y][x];
for(const[offsetX,offsetY]ofdirections){
constnextXY=[x+offsetX,y+offsetY];
const[nextX,nextY]=nextXY;
if(nextX>=0&&nextY>=0&&nextXconstnextStatus=dp[nextY][nextX];
constisObstacle=grid[nextY][nextX]==1;
letavailable=false;
if(!
isObstacle){
for(leti=0;iconstnextStep=status[i]+1;
if(nextStepnextStatus[i]=nextStep;
available=true;
}
}
}
else{
for(leti=0;iconstnextStep=status[i]+1;
if(nextStepnextStatus[i+1]=nextStep;
available=true;
}
}
}
if(available)queue.push(nextXY);
}
}
}
lettotalSteps=Math.min(...dp[height-1][width-1]);
returntotalSteps==Infinity?
-1:
totalSteps;
};