与えられた m * n
各セルのいずれかであるグリッド、 0
(空)または 1
(障害物)。1つのステップでは、から、空のセルに左または右、下、上に移動することができます。
左上隅から歩くためのステップ数の最小値を返します (0, 0)
右下隅に (m-1, n-1)
あなたが最もに排除することができますことを考えると k
、障害物を。それが不可能な場合は、このような歩行リターンを見つけるために-1。
例1:
入力:
グリッド=
[0,0,0]、
[1,1,0]、
[0,0,0]、
[0,1,1]、
[0,0,0]、
K = 1つの
出力:6
説明:
障害物を除去することなく、最短経路は10である
位置に1つの障害物除去(3,2)との最短経路6.このような経路があります(0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (3,2) -> (4,2)
。
例2:
入力:
グリッド=
[0,1,1]、
[1,1,1]、
[1,0,0]、
K = 1つの
出力:-1
説明:
我々は、そのような見つけるために少なくとも2つの障害物を除去するために必要散歩。
制約:
grid.length == m
grid[0].length == n
1 <= m, n <= 40
1 <= k <= m*n
grid[i][j] == 0 or 1
grid[0][0] == grid[m-1][n-1] == 0
問題の意味:マトリックスを考えるは、[N-1、M-1]及び方法に最もk番目の障害物を除去するステップの最小数に行くQ [0、0]から、上下左右に移動させることができます。
ソリューション:明らかに、動的プログラミングの問題。DFSは、動的プログラミング格納された結果は、ダブルカウントを避けるために計算されている使用して繰り返し、単純な計算がたくさんあります。
int dirs[4][2] = {-1,0, 0,1,1,0,0,-1}; int dp[41][41][1700]; bool flag[41][41]; class Solution { public: vector<vector<int>> _grid; bool inside(int x, int y){ if(x>=0 && x<_grid.size() && y>=0 &&y<_grid[0].size()) return true; return false; } int shortestPath(vector<vector<int>>& grid, int k) { _grid = grid; memset(dp, -1, sizeof(dp)); memset(flag, 0 ,sizeof(flag)); int ret = dfs(0, 0, k); return ret>=INT_MAX/2 ? -1 : ret; } int dfs(int x, int y, int k){ if(k<0) return INT_MAX/2; if(dp[x][y][k] != -1) return dp[x][y][k]; if(x==_grid.size()-1 && y==_grid[0].size()-1) return dp[x][y][k] = 0; int ret = INT_MAX/2; for(int i=0; i<4; i++){ int xx = x+dirs[i][0]; int yy = y+dirs[i][1]; if(inside(xx, yy) && !flag[xx][yy]){ flag[xx][yy] = true; int temp = INT_MAX/2; if(_grid[xx][yy]) temp = dfs(xx, yy, k-1); else temp = dfs(xx, yy, k); ret = min(ret, 1+temp); flag[xx][yy] = false; } } return dp[x][y][k] = ret; } };