bfs vis数组 最短路

vis的目的其实并不是已经访问过哪些节点,而是记录【[在当前步骤] 或 [之前的步骤]】中已经访问过的状态。因为之前已经访问过了这些状态,而之前那些访问用的步骤更少,因此之后就没必要再次访问这些状态了。

当用bfs用于记录到达某个状态的步骤时,则若某个节点 【曾经访问过】或【通步骤的其他状态已经将这个节点加入队列】,则不用再将这个节点加入队列:

 while (!sourceq.empty()) {
      level_count = sourceq.size();
      while ((level_count--) > 0) {
        auto p = sourceq.front();
        sourceq.pop(); 
        for (int i=0; i<4; i++) {
          int subx = p.first + dx[i];
          int suby = p.second + dy[i];
          if (subx >= 0 && suby >= 0 && subx < m && suby < n) {
            if (A[subx][suby] == 1) {
              return step;
            } else if (A[subx][suby] == 0 && vis2[subx][suby] == 0){
              sourceq.push({subx,suby});
              vis2[subx][suby]=1;
            }
          }
        }
      }

或者:

while (!sourceq.empty()) {
      level_count = sourceq.size();
      while ((level_count--) > 0) {
        auto p = sourceq.front();
        sourceq.pop();
        if (vis2[p.first][p.second] == 1) {
          continue;
        }
        vis2[p.first][p.second] = 1;
        for (int i=0; i<4; i++) {
          int subx = p.first + dx[i];
          int suby = p.second + dy[i];
          if (subx >= 0 && suby >= 0 && subx < m && suby < n) {
            if (A[subx][suby] == 1) {
              return step;
            } else if (A[subx][suby] == 0){
              sourceq.push({subx,suby});
            }
          }
        }
      }
      step++;
    }

但不能这样:

 while (!sourceq.empty()) {
      level_count = sourceq.size();
      while ((level_count--) > 0) {
        auto p = sourceq.front();
        sourceq.pop();
        // 1:
        if (vis2[p.first][p.second] == 1) {
          continue;
        }
        vis2[p.first][p.second] = 1;
        for (int i=0; i<4; i++) {
          int subx = p.first + dx[i];
          int suby = p.second + dy[i];
          if (subx >= 0 && suby >= 0 && subx < m && suby < n) {
            if (A[subx][suby] == 1) {
              return step;
            } else if (A[subx][suby] == 0 && vis2[subx][suby] == 0){
              // 2:
              sourceq.push({subx,suby});
              vis2[subx][suby]=1;
            }
          }
        }
      }

这样做的话,因为2处已经将vis2[subx][suby]设置为1,则访问这个节点时,因为1处代码的存在,会直接跳过访问这个节点。

另外,若有多个起始状态的bfs出现了tle,可能的原因是:队列中的起始状态有重复的,不妨试试没有重复时可不可以度过难关。做leetcode::934::最短的桥时就因为这种原因tle了