class Solution { public: int direction[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; int res=INT_MAX; int shortestPath(vector<vector<int>>& grid, int k) { //这种题感觉就是递归回溯 但是有两个限制 一个是求最小步数(动态规划) 然后是求能够消除指定k个 障碍 //如果不ok就回溯一个 //lets have a try //好久没写bfs了 int m=grid.size(),n=grid[0].size(); vector<vector<int>> memo(m,vector<int>(n,0)); dfs(grid,memo,0,0,k,m,n,0); if(res==INT_MAX) return -1; return res; } bool inAera(int x,int y,int m,int n){ //judge aera return x>=0 &&x<m &&y>=0 &&y<n; } void dfs(vector<vector<int>>& grid,vector<vector<int>> &memo,int x,int y,int k,int m,int n,int count) { if(x==m-1&&y==n-1 &&k>=0) { res=min(res,count); return; } if(k<0) return; //如何剪枝呢? if(grid[x][y]==1 && k==0) return; //当前格子做一个标注表示走过了 memo[x][y]=1; for(int i=0;i<4;++i) { int x_next=x+direction[i][0]; int y_next=y+direction[i][1]; if(inAera(x_next,y_next,m,n) && k>=0 &&memo[x_next][y_next]==0){ dfs(grid,memo,x_next,y_next,k-grid[x][y],m,n,count+1); } } memo[x][y]=0;//回溯 return; } };利用队列实现广度优先:
class Solution { public: int direction[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; int res=INT_MAX; int shortestPath(vector<vector<int>>& grid, int k) { int m=grid.size(),n=grid[0].size(); vector<vector<int>> memo(m,vector<int>(n,-1));//为啥是-1呢? //利用队列实现bfs if(k>=m+n-2) return m+n-2; //步数有富裕 queue<tuple<int,int,int>>ss; memo[0][0]=k; ss.push({0,0,k}); int level=0; while(!ss.empty()){ auto sz=ss.size(); ++level; while(sz--){ //广度优先 auto[x,y,ck]=ss.front(); ss.pop(); for(int i=0;i<4;++i){ int x_next=x+direction[i][0]; int y_next=y+direction[i][1]; if(inAera(x_next,y_next,m,n)){ int nk=ck-grid[x_next][y_next]; if(nk<0) continue; if(memo[x_next][y_next]>=nk) continue;//不是最短的 if(x_next==m-1 && y_next==n-1) { return level; } memo[x_next][y_next]=nk; ss.push({x_next,y_next,nk}); } } } } return -1; } bool inAera(int x,int y,int m,int n){ //judge aera return x>=0 &&x<m &&y>=0 &&y<n; } };