问题:
给定n*m由0和1构成的二维数组。
0代表通路
1代表障碍
求从左上角格子(0,0)出发,要到达右下角格子(n-1,m-1)
可以最多遇到 k 个障碍,至少需要多少步能到达。
若不能做到,返回-1。
Example 1: Input: grid = [[0,0,0], [1,1,0], [0,0,0], [0,1,1], [0,0,0]], k = 1 Output: 6 Explanation: The shortest path without eliminating any obstacle is 10. The shortest path with one obstacle elimination at position (3,2) is 6. Such path is (0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (3,2) -> (4,2). Example 2: Input: grid = [[0,1,1], [1,1,1], [1,0,0]], k = 1 Output: -1 Explanation: We need to eliminate at least two obstacles to find such a walk. Constraints: 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
解法:BFS
- 状态:
- 当前位置(x,y)
- 当前剩余可用遇障碍数 k
- 选择:
- 上下左右4个方向,
- 其中 k>0 时,grid[next.x][next.y] 可以==1。下一个状态 next.k--
- 否则,grid[next.x][next.y] == 0 才可以选择。
- 上下左右4个方向,
代码参考:
1 class State { 2 public: 3 int x; 4 int y; 5 int k; 6 State(){} 7 State(int x_1, int y_1, int k_1) { 8 x=x_1; 9 y=y_1; 10 k=k_1; 11 } 12 string to_string() { 13 return ::to_string(x) + "_" + ::to_string(y) + "_" + ::to_string(k); 14 } 15 }; 16 class Solution { 17 public: 18 int m,n; 19 int dir[5] = {1,0,-1,0,1}; 20 int shortestPath(vector<vector<int>>& grid, int k) { 21 int step = 0; 22 n = grid.size(); 23 m = grid[0].size(); 24 queue<State> q; 25 unordered_set<string> visited; 26 State st(0,0,k), cur, next; 27 q.push(st); 28 visited.insert(st.to_string()); 29 while(!q.empty()) { 30 int sz = q.size(); 31 for(int k=0; k<sz; k++) { 32 cur = q.front(); 33 q.pop(); 34 if(cur.x==n-1 && cur.y==m-1) return step; 35 for(int d=1; d<5; d++) { 36 next.x = cur.x+dir[d-1]; 37 next.y = cur.y+dir[d]; 38 next.k = cur.k; 39 if(next.x<0 || next.y<0 || next.x>=n || next.y>=m) continue; 40 if(grid[next.x][next.y] == 1 && next.k<=0) continue; 41 else if(grid[next.x][next.y] == 1 && next.k>0) next.k--; 42 if(visited.insert(next.to_string()).second) { 43 q.push(next); 44 } 45 } 46 } 47 step++; 48 } 49 return -1; 50 } 51 };