题解 Y
首先发现每个状态可以被压成一个 \(\{(x_1, y_1), (x_2, y_2)\}\) 的二元组,分别表示空白格子和指定格子的位置
于是可以状压,复杂度 \(O(qn^2m^2)\),因为-1判错了挂了十分
其实这个方法开O2可以AC
然后正解:
貌似是处理这种地图固定,状压移动求最短路且询问数很多的题的一种套路
发现指定格子要想移动,空白格子肯定得在它旁边
于是这样的状态有 \(4nm\) 种,而且从某些状态可以走一定步数到达下一个状态
于是将这些状态抽离出来,在这些状态上建图,就可以用最短路求出到达某种状态的最小步数
发现初始状态下空白格子不一定在指定格子旁边,所以BFS把它挪过去
注意特判初始指定格子就在目标格子上的情况
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define fir first
#define sec second
#define make make_pair
// #define int long long
char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m, k;
bool mp[32][32];
namespace force{
int dp[32][32][32][32], top;
const int dlt[][2]={{-1,0},{0,1},{1,0},{0,-1}};
struct st{int x1, y1, x2, y2; st(){} st(int a, int b, int c, int d):x1(a),y1(b),x2(c),y2(d){}}sta[30*30*30*30+10];
queue<st> q;
void solve() {
int ex, ey, sx, sy, tx, ty;
memset(dp, -1, sizeof(dp));
for (int i=1; i<=k; ++i) {
// cout<<"i: "<<i<<endl;
ex=read(); ey=read(); sx=read(); sy=read(); tx=read(); ty=read();
// memset(dp, -1, sizeof(dp));
while (top) dp[sta[top].x1][sta[top].y1][sta[top].x2][sta[top].y2]=-1, --top;
while (q.size()) q.pop();
dp[sx][sy][ex][ey]=0;
sta[++top]=st(sx, sy, ex, ey);
q.push(st(sx, sy, ex, ey));
st u;
while (q.size()) {
u=q.front(); q.pop();
// cout<<1<<endl;
// cout<<u.x1<<' '<<u.y1<<' '<<u.x2<<' '<<u.y2<<endl;
int dp_this=dp[u.x1][u.y1][u.x2][u.y2];
for (int j=0,x,y; j<4; ++j) {
// cout<<"j: "<<j<<endl;
x=u.x2+dlt[j][0], y=u.y2+dlt[j][1];
// cout<<"xy: "<<x<<' '<<y<<endl;
if (x>=1&&x<=n&&y>=1&&y<=m&&mp[x][y]) {
if (x==u.x1&&y==u.y1) {
if (dp[u.x2][u.y2][u.x1][u.y1]==-1) {
dp[u.x2][u.y2][u.x1][u.y1]=dp_this+1;
sta[++top]=st(u.x2, u.y2, u.x1, u.y1);
q.push(st(u.x2, u.y2, u.x1, u.y1));
if (u.x2==tx&&u.y2==ty) {
printf("%d\n", dp_this+1);
goto jump;
}
}
}
else {
if (dp[u.x1][u.y1][x][y]==-1) {
dp[u.x1][u.y1][x][y]=dp_this+1;
sta[++top]=st(u.x1, u.y1, x, y);
q.push(st(u.x1, u.y1, x, y));
}
}
}
}
}
printf("%d\n", dp[tx][ty][ex][ey]);
jump: ;
}
}
}
namespace task{
int dp[32][32], f[32][32][4][4], head[4096], dis[4096], size;
bool vis[N];
struct edge{int to, next, val;}e[32768];
inline void add(int s, int t, int w) {e[++size].to=t; e[size].val=w; e[size].next=head[s]; head[s]=size;}
const int dlt[][2]={{-1,0},{1,0},{0,1},{0,-1}};
queue<pair<int, int>> q;
queue<int> q2;
void bfs(int sx, int sy, int dx, int dy) {
memset(dp, -1, sizeof(dp));
while (q.size()) q.pop();
dp[sx][sy]=0; dp[dx][dy]=INF;
q.push(make(sx, sy));
pair<int, int> u;
while (q.size()) {
u=q.front(); q.pop();
int dp_this=dp[u.fir][u.sec];
for (int i=0,x,y; i<4; ++i) {
x=u.fir+dlt[i][0], y=u.sec+dlt[i][1];
if (x>=1&&x<=n&&y>=1&&y<=m&&mp[x][y]&&dp[x][y]==-1) {
dp[x][y]=dp_this+1;
q.push(make(x, y));
}
}
}
}
inline int num(int i, int j, int k) {return 4*((i-1)*m+j)+k;}
void spfa() {
int u;
while (q2.size()) {
u=q2.front(); q2.pop();
vis[u]=0;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (dis[u]+e[i].val < dis[v]) {
dis[v]=dis[u]+e[i].val;
if (!vis[v]) q2.push(v), vis[v]=1;
}
}
}
}
void solve() {
int ex, ey, sx, sy, tx, ty;
memset(dp, -1, sizeof(dp));
memset(f, 0x3f, sizeof(f));
memset(head, -1, sizeof(head));
for (int i=1; i<=n; ++i) {
for (int j=1; j<=m; ++j) if (mp[i][j]) {
for (int k=0,x,y; k<4; ++k) {
x=i+dlt[k][0], y=j+dlt[k][1];
if (!mp[x][y]) continue;
bfs(x, y, i, j);
// cout<<"bfs: "<<i<<' '<<j<<endl;
// cout<<"dp: "<<endl;
// for (int i=1; i<=n; ++i) {for (int j=1; j<=m; ++j) cout<<dp[i][j]<<' '; cout<<endl;}
for (int h=0,s,t,t1,t2; h<4; ++h) if (h!=k) {
s=i+dlt[h][0], t=j+dlt[h][1];
if (!mp[s][t] || dp[s][t]==-1 || dp[s][t]==INF) continue;
f[i][j][k][h]=dp[s][t];
// printf("f[%d][%d][%d][%d]=%d\n", i, j, k, h, f[i][j][k][h]);
t1=num(i, j, k); t2=num(i, j, h);
add(t1, t2, dp[s][t]); add(t2, t1, dp[s][t]);
// printf("add: (%d, %d, %d), (%d, %d, %d)=%d\n", i, j, k, i, j, h, dp[s][t]);
}
add(num(i, j, k), num(x, y, k^1), 1);
add(num(x, y, k^1), num(i, j, k), 1);
// printf("add: (%d, %d, %d), (%d, %d, %d)=%d\n", x, y, k^1, i, j, k, 1);
}
}
}
for (int i=1; i<=k; ++i) {
ex=read(); ey=read(); sx=read(); sy=read(); tx=read(); ty=read();
bfs(ex, ey, sx, sy);
if (sx==tx&&sy==ty) {puts("0"); continue;}
memset(dis, 0x3f, sizeof(dis));
for (int j=0,x,y; j<4; ++j) {
x=sx+dlt[j][0], y=sy+dlt[j][1];
if (!mp[x][y] || dp[x][y]==-1) continue;
dis[num(sx, sy, j)]=dp[x][y];
// cout<<"pre: "<<dp[x][y]<<endl;
q2.push(num(sx, sy, j));
}
spfa();
// cout<<"dis: "<<dis[num(2, 2, 0)]<<endl;
int ans=INF;
for (int j=0,x,y; j<4; ++j) {
x=tx+dlt[j][0], y=ty+dlt[j][1];
if (!mp[x][y]) continue;
ans=min(ans, dis[num(tx, ty, j)]);
}
printf("%d\n", ans==INF?-1:ans);
jump: ;
}
}
}
signed main()
{
// freopen("y.in", "r", stdin);
// freopen("y.out", "w", stdout);
n=read(); m=read(); k=read();
for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) mp[i][j]=read();
// force::solve();
task::solve();
return 0;
}