为什么类似的网格左上角走到右下角的题目,一个BFS超时,一个BFS不超时
来源:9-2 第一个动态规划问题 Climbing Stairs
慕斯卡8072790
2021-11-20
题目一:
// LeetCode 64号问题,超时代码
// 我的第一思路就是BFS搜索求最短路径,然后就超时了
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
class Solution {
private:
int R, C;
int dirs[2][2] = {{1, 0}, {0, 1}};
struct node
{
int x, y, s;
bool operator<(const node o) const {
return s > o.s;
}
}cur, nextN;
bool inArea(int x, int y) {
return x >= 0 && x < R && y >= 0 && y < C;
}
public:
int minPathSum(vector<vector<int>>& grid) {
R = grid.size();
C = grid[0].size();
priority_queue<node> que;
que.push({0, 0, grid[0][0]});
if( 0 == R-1 && 0 == C-1 ) {
return grid[0][0];
}
while( !que.empty() ) { // 尝试自己分析复杂度,觉得最差情况每次push两倍节点,所以是O(2^n)复杂度
cur = que.top();
que.pop();
for( int d = 0 ; d < 2 ; d++ ) {
int nextx = cur.x + dirs[d][0];
int nexty = cur.y + dirs[d][1];
if( inArea(nextx, nexty) ) {
nextN.x = nextx;
nextN.y = nexty;
nextN.s = grid[nextx][nexty] + cur.s;
que.push(nextN);
if( nextx == R-1 && nexty == C-1 )
return nextN.s;
}
}
}
return -1;
}
};
int main()
{
vector<vector<int>> vec = {{1, 3, 1}, {1, 5, 1}, {4, 2, 1}};
cout<<Solution().minPathSum(vec)<<endl;
return 0;
}
题目二:
为什么这类似的题目又不超时了?
写回答
2回答
-
你的第一个代码的时间复杂度不是 V + E 的。bfs 里记录了 ( 顶点 + 当前访问这个顶点的时候对应的 cost)两个信息,所以,bfs 访问的状态数是 (顶点总数 * cost 的可能性) 这么多。也就是每个顶点在不同的 cost 下是会不断访问的。你可以在循环里不断地打印一下你的 queue 的 size,看看是不是在呈指数级的上升。
这里的关键是,bfs 处理的是无权图的最短路径问题,而第一个问题是一个带权图。如果你用最短路径的思路做,应该用 dijkstra。而由于这个问题限制了每一步只能向右或者向下走,所以存在最优子结构,可以使用 dp。
继续加油!:)
112021-11-20 -
慕斯卡8072790
提问者
2021-11-20
突然想起,BFS的时间复杂度是O(V+E),而dp的复杂度是O(V),这两个复杂度的差距应该只是 BFS的系数大一些呀,也不至于TLE溢出吧。
00
相似问题