https://www.acwing.com/problem/content/177/

双端队列BFS

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N = 600;
using PPI = pair<int, int>;
char tb[N][N]; //储存电线初始状态
int dis[N][N];  //储存起点到各点的距离
bool vis[N][N]; 
int m, n;

void bfs()
{


    deque<PPI> q;
    int mx[4] = {
   1, -1, -1, 1}; int my[4] = {
   1, -1, 1, -1}; //四个移动方向, 右下 左上 右上 左下
    int cx[4] = {
   0, -1, -1, 0}; int cy[4] = {
   0, -1, 0, -1};
    char wire[] = "\\\\//";     //电线的四种状态
    memset(vis, false, sizeof vis);
    memset(dis, 0x3f, sizeof dis);
    dis[0][0] = 0;
    q.push_back({
   0, 0});

    while (!q.empty()) {

        auto f = q.front();
        q.pop_front();
        if (vis[f.x][f.y])
            continue;
        vis[f.x][f.y] = true;
        //出队时才能再设为不可访问
        if (f.x == m and f.y == n) {

            cout << dis[m][n] << endl;
            return;
        }
        for (int i = 0; i < 4; i++) {

            int nx = f.x + mx[i], ny = f.y + my[i];
            int use_x = f.x + cx[i], use_y = f.y + cy[i]; //现在在使用哪个格子的电线
            if (nx >= 0 and nx < m + 1 and ny >= 0 and ny < n + 1) {

                int w = (tb[use_x][use_y] != wire[i]);    //若不需要转动电线则边权为0, 否则边权为1
                if (dis[nx][ny] <= dis[f.x][f.y] + w)
                    continue;
                if (w) {

                    //边权为1则尾插
                    dis[nx][ny] = dis[f.x][f.y] + w;
                    q.push_back({
   nx, ny});
                }
                else {

                    //头插
                    dis[nx][ny] = dis[f.x][f.y];
                    q.push_front({
   nx, ny});
                }
            }
        }
    }
    printf("NO SOLUTION\n");
}

int main() {

#ifndef ONLINE_JUDGE
    freopen("D:/VS CODE/C++/in.txt", "r", stdin);
    freopen("D:/VS CODE/C++/out.txt", "w", stdout);
#endif
    int t;
    cin >> t;
    while (t--) {

        cin >> m >> n;
        for (int i = 0; i < m; i++) {

            for (int j = 0; j < n; j++) {

                cin >> tb[i][j];
            }
        }
        if ((m + n) & 1) {

            //x y 和为奇数的点无法到达
            printf("NO SOLUTION\n");
        }
        else
            bfs();
    }

    fclose(stdin);
    fclose(stdout);
    return 0;
}