双端队列bfs

题意:

一个 的图,现在有一束激光从左上角往右边射出,每遇到 '#',你可以选择光线往四个方向射出,或者什么都不做,问最少需要多少个 '#' 往四个方向射出才能使光线在第 行往右边射出。
此题目正解不是 0-1 BFS 但是适用 0-1 BFS 可以不需要思考过程,赛时许多大佬都是这么做的。
做法很简单,一个方向射出不需要花费(0),而往四个方向射出需要花费(1),然后直接来就可以了。

适用条件:0-1图

#include <bits/stdc++.h>
using namespace std;
#define INF (1 << 29)
int n, m;
char grid[1001][1001];
int dist[1001][1001][4];
int vis[1001][1001][4];
int fx[] = {1, -1, 0, 0};
int fy[] = {0, 0, 1, -1};
deque<int> q;

void add_front(int x,int y,int dir,int d){
    if(dist[x][y][dir]>d){
        dist[x][y][dir]=d;
        q.push(dir);
        q.push(y);
        q.push(x);
    }
}

void add_back(int x,int y,int dir,int d){
    if(dist[x][y][dir]>d){
        dist[x][y][dir]=d;
        q.push(x);
        q.push(y);
        q.push(dir);
    }
}

int main(){
    cin >> n >> m;
  for (int i = 0; i < n; i++) cin >> grid[i];

  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
      for (int k = 0; k < 4; k++) dist[i][j][k] = INF;

      add_front(n - 1, m - 1, 3, 0);

    while (!q.empty()) {
    int x = q[0], y = q[1], dir = q[2];
    q.pop_front();
    q.pop_front();
    q.pop_front();
    if (vis[x][y][dir]) continue;
    vis[x][y][dir] = true;
    int d = dist[x][y][dir];
    int nx = x + fx[dir], ny = y + fy[dir];
    if (nx >= 0 && nx < n && ny >= 0 && ny < m) add_front(nx, ny, dir, d);
    if (grid[x][y] == '#')
      for (int i = 0; i < 4; i++)
        if (i != dir) add_back(x, y, i, d + 1);
  }
  if (dist[0][0][3] == INF)
    cout << -1 << endl;
  else
    cout << dist[0][0][3] << endl;
  return 0;

}