#include<bits/stdc++.h>
using namespace std;

#define x first
#define y second

typedef pair<int, int> PII;

const int N = 35, M = 3610, K = 4 * M, INF = 0x3f3f3f3f;
//N是格子边长, M是状态个数, K是边的个数

int n, m, Q;
int h[M], e[K], ne[K], w[K], idx;

int dist1[N][N], dist2[M];
//dist1是网格bfs(箱子不动人动), dist2 spfa
int g[N][N];
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
bool st[M];

void add(int a, int b, int c)
{
    e[idx] = b, ne[idx] = h[a], w[idx] = c;
    h[a] = idx++;
}

int get(int i, int j, int k) //把状态变成点
{
    return ((i - 1) * m +  j - 1) * 4 + k;
}

void bfs(int px, int py, int bx, int by, int dir)
{
    memset(dist1, 0x3f, sizeof dist1);
    dist1[px][py] = dist1[bx][by] = 0;
    queue<PII> q;
    q.push({px, py});

    while(q.size())
    {
        auto t = q.front();
        q.pop();

        for(int i = 0; i < 4; i++)
        {
            int x = t.x + dx[i], y = t.y + dy[i];
            if(g[x][y] && dist1[x][y] > dist1[t.x][t.y] + 1)
            {
                dist1[x][y] = dist1[t.x][t.y] + 1;
                q.push({x, y});
            }
        }
    }

    if(dir == -1) return; //只需要广搜 不需要建图

    int id = get(bx, by, dir);

    for(int i = 0; i < 4; i++)
    {
        if(i != dir) //如果需要加边
        {
            int x = bx + dx[i], y = by + dy[i];
            if(dist1[x][y] < INF)
            {
                add(id, get(bx, by, i), dist1[x][y]);
            }
        }
    }

    add(id, get(px, py, dir ^ 2), 1);
}

int spfa(int sx, int sy, int tx, int ty)
{
    queue<int> q;
    memset(dist2, 0x3f, sizeof dist2);
    for(int i = 0; i < 4; i++)
    {
        int x = sx + dx[i], y = sy + dy[i];
        if(dist1[x][y] < INF)
        {
            int k = get(sx, sy, i);
            dist2[k] = dist1[x][y];
            q.push(k);
            st[k] = 1;
        }
    }

    while(q.size())
    {
        auto t = q.front();
        q.pop();
        st[t] = 0;
        for(int i = h[t]; i != -1; i = ne[i])
        {

            int j = e[i];
            if(dist2[j] > dist2[t] + w[i])
            {
                dist2[j] = dist2[t] + w[i];
                if(!st[j])
                {
                    q.push(j);
                    st[j]  = 1;
                }
            }
        }
    }

    int res = INF;
    for(int i = 0; i < 4; i++)
        res = min(res, dist2[get(tx, ty, i)]); //4个方向最短路是谁
    
    if(res == INF) res = -1;
    return res;
}

int main()
{
    cin >> n >> m >> Q;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            cin >> g[i][j];
    
    memset(h, -1, sizeof h);

    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++) //枚举箱子的位置(i, j)
            if(g[i][j])
            {
                for(int k = 0; k < 4; k++)
                {
                    int x = i + dx[k], y = j + dy[k];
                    if(g[x][y])
                        bfs(x, y, i, j, k);
                }
            }

    while(Q --)
    {
        int ex, ey, sx, sy, tx, ty;
        cin >> ex >> ey >> sx >> sy >> tx >> ty;

        if(sx == tx && sy == ty) cout << 0 << endl;
        else
        {
            bfs(ex, ey, sx, sy, -1);
            cout << spfa(sx, sy, tx, ty) << endl;
        }
    }
    return 0;
}

/*
最后一步之前,将白格移动到s的邻格

任何一个格子a 从(i, j)移动到相邻的格子b,需要让白格先移动到b
之后交换a与白格。a下一步还是要继续往其他方向移动,所以白格
仍然需要移动到a的某个相邻格。

设置一个状态(i, j, k)表示格子s在(i, j), 白格在(i, j)的方向k处
其中k=0 1 2 3 表示四个方向

转移状态时:
1.白格与s进行交换,在状态(si, sj, k)与(ei, ej, k) 之间连一条边,边权为1。
2.白格移动到了一个与s相邻的位置(x',y'),
此时状态(si, sj, k) 与 状态(si, sj, i)之间连边,边权为dis[x'][y']

我们将状态作为点,花费作为边,建图.


spfa  (tx, ty, 0 / 1 / 2/ 3) 到(sx, sy, 0/1/2/3)最短路

*/

0 条评论

目前还没有评论...