【BFS】Ybt_电路维修

电路维修

给你个n*m的格子方阵,格子上标有 \ 或者 / ,代表这个格子左上角与右下角联通 或者 右上角与左下角联通。 你可以选择旋转格子,使得它变成另外一种情况的联通。要你联通方阵最左上角和最右下角。
有多组数据。


可以将方格的角视作一个点,它通往隔壁的点如果不需要转格子,那么建边权值为0,需要转格子,那么权值为1.
于是就成了求最短路的问题。
但是普通地跑 SPFA 会挂掉。
于是改成双端队列求解(还跑得快一点)。


代码

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;

int T, n, m, t, in[400000], Z[400000], l[400000];
char c;

struct asdf {
    
    
    int bh, next, z;
} A[1000001];
void bfs() {
    
    
    deque<int> Q;
    Q.push_back(0);  //加入队尾
    while (!Q.empty()) {
    
      //Spfa
        int bh = Q.front();
        Q.pop_front();
        in[bh] = 1;
        for (int i = l[bh]; i; i = A[i].next)
            if (Z[bh] + A[i].z < Z[A[i].bh]) {
    
    
                if (!in[A[i].bh]) {
    
       //是否处理过了
                    if (A[i].z == 0)  //如果权值为0,丢入队列头
                        Q.push_front(A[i].bh);
                    else  //权值为1,丢入队列尾
                        Q.push_back(A[i].bh);
                }
                Z[A[i].bh] = Z[bh] + A[i].z;  //更新值
            }
    }
}

void add(int x1, int y1, int x2, int y2, int z) {
    
      //建边,我给每个点都赋了个编号...
    int bh1 = x1 * (m+1) + y1;
    int bh2 = x2 * (m+1) + y2;
    A[++t] = (asdf){
    
     bh2, l[bh1], z };
    l[bh1] = t;
    A[++t] = (asdf){
    
     bh1, l[bh2], z };
    l[bh2] = t;
}

void work() {
    
    
    memset(Z, 0x7f, sizeof(Z));
    memset(l, 0, sizeof(l));
    memset(in, 0, sizeof(in));
    t = 0;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) {
    
      //输入,建边
            c = getchar();
            while (c != '/' && c != '\\') c = getchar();
            if (c == '/') {
    
    
                add(i - 1, j - 1, i, j, 1);
                add(i, j - 1, i - 1, j, 0);
            } else {
    
    
                add(i - 1, j - 1, i, j, 0);
                add(i, j - 1, i - 1, j, 1);
            }
        }
    Z[0] = 0;
    bfs();
    if (Z[(n + 1) * (m + 1) - 1] < 1000000)  //输出答案
        printf("%d\n", Z[(n + 1) * (m + 1) - 1]);
    else
        printf("NO SOLUTION\n");
}

int main() {
    
    
    scanf("%d", &T);  //多组数据。
    while (T--) work();
}

猜你喜欢

转载自blog.csdn.net/qq_42937087/article/details/112976845