题解【洛谷P4667】[BalticOI 2011 Day1]Switch the Lamp On

题面

一道可以使用双端队列 BFS 做的最短路问题。

我们首先考虑建图:

  • 对于每一个方格,如果它的方向是 ,那么将它的左上角和右下角连一条长度为 (0) 的边,将它的左下角和右上角连一条长度为 (1) 的边;
  • 否则,如果它的方向是 /,那么将它的左上角和右下角连一条长度为 (1) 的边,将它的左下角和右上角连一条长度为 (0) 的边。

因此我们的最终答案就是 (dist_{n,m})

考虑如何快速求出 (dist_{n,m})

我们可以用一个双端队列,模拟 Dijkstra 算法的流程:

  • 对于每一个点,向它的左上、右上、左下、右下方的点扩展。假设当前点是 ((i,j))
  • 然后,判断当前方格的方向是否连接当前节点和要扩展的节点。
  • 如果是,那么将 (dist_{i,j}) 放到双端队列的队头。
  • 否则,就将 (dist_{i,j}+1) 放到双端队列的队尾。

这样说可能会有一些难懂,具体的实现还需参考代码。

#include <bits/stdc++.h>

using namespace std;

const int N = 503;
const int dx[] = {-1, -1, 1, 1}, dy[] = {-1, 1, 1, -1}; //要扩展的点的偏移量
const int ix[] = {-1, -1, 0, 0}, iy[] = {-1, 0, 0, -1}; //当前节点对应的四个方格在输入的字符串中的偏移量
const char xk[] = "\/\/"; //能够正确连接当前节点与要扩展的点的电线方向

int n, m, t;
char s[N][N];
int vis[N][N], dist[N][N];

inline int bfs()
{
    memset(dist, 0x3f, sizeof dist);
    memset(vis, 0, sizeof vis);
    deque <pair <int, int> > q; //双端队列
    q.push_front(make_pair(0, 0));
    dist[0][0] = 0; //初始化
    while (!q.empty())
    {
        int x = q.front().first, y = q.front().second;
        q.pop_front();
        if (x == n && y == m) return dist[x][y]; //到达了终点
        if (vis[x][y]) continue;
        vis[x][y] = 1;
        for (int i = 0; i < 4; i+=1)
        {
            int xx = x + dx[i], yy = y + dy[i]; //要扩展的节点的横纵坐标
            if (xx < 0 || xx > n || yy < 0 || yy > m) continue; //越界
            int cx = x + ix[i], cy = y + iy[i]; //当前字符在输入字符串中的下标
            int w = (xk[i] != s[cx][cy]); //方向是否正确
            int d = dist[x][y] + w; //当前要旋转的最少次数
            if (dist[xx][yy] >= d) //可以更新最少次数
            {
                dist[xx][yy] = d;
                if (!w) q.push_front(make_pair(xx, yy)); //加到队头
                else q.push_back(make_pair(xx, yy)); //加到队尾
            }
        }
    }
    return -1;
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; i+=1) scanf("%s", s[i]);
    if ((n + m) & 1) puts("NO SOLUTION"); //(n,m) 永远无法到达,那么直接输出无解
    else cout << bfs() << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/xsl19/p/12380226.html