#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
class Solution {
private:
int cost[40][40];
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};
public:
int shortestPath(vector<vector<int>>& grid, int k) {
const int tx = grid.size()-1;
const int ty = grid[0].size()-1;
if (tx == 0 && ty == 0) return 0;
vector<pair<int, int>> currNode,nextNode;
memset(cost, 0x3f, 40 * 40 * sizeof(int));
cost[0][0] = grid[0][0];
currNode.push_back(make_pair(0, 0));
int step = 1;
while(!currNode.empty())
{
for(auto p: currNode)
{
for(int i=0; i<4; i++)
{
const int nx = p.first + dx[i];
const int ny = p.second + dy[i];
//到达终点
if (nx == tx && ny == ty) return step;
//出界跳出循环
if (ny < 0 || ny > ty||nx < 0 || nx > tx) continue;
//剪枝,新扩张区域cost变大或超出k则不扩张该位置
if (cost[p.first][p.second] + grid[nx][ny] >= cost[nx][ny] || cost[p.first][p.second] + grid[nx][ny] > k)
continue;
cost[nx][ny] = cost[p.first][p.second] + grid[nx][ny];
nextNode.push_back(make_pair(nx, ny));
}
}
swap(nextNode, currNode);
nextNode.clear();
step++;
}
return -1;
}
};
设计思想
- 主要思想为BFS;
- 传统题不能消除障碍,思路为直接使用队列存储向四方向扩张的“可行位置”,然后以队列首元素为“基准位置”进行扩张,将扩张位置存储至队列,然后删除队首元素并循环;所以本题需要存储三维数据,包含二维坐标,和到当前位置的minCost(最少清除的障碍物数量),初始化cost为无穷(0x3f);
Tips
DP(动态规划)一般用于解决两方向移动,即左下/右上;本题可能涉及四方向S形走位,使用DP必须添加额外条件,个人倾向于“DP难以解决此问题”的结论。