這道題,寫的很醉啊。。。。
這種搜索的題,還帶一點DP,各種bug調了好久,
思路:
60分做法就直接bfs亂搞,60分到手;
ac套路:
首先預處理出f[i][j][k]狀態,對於點ij,空格在k方向就是開個【30】【30】【4】的數組,再用鄰接表存下來,spfa跑一邊最短路就好了,注意終點和起點是可能重合的;
code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
const int N=35;
const int M=400010;
const int inf=1000000000;
using namespace std;
bool vis[N][N];
const int d[4][2]={{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
struct point{
int x, y, d;
};
int n,m,q,map[N][N];
int bfs(int x1, int y1, int x2, int y2){
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)vis[i][j]=false;
vis[x1][y1]=true;
queue<point>q;
q.push((point){x1, y1, 0});
while(!q.empty()){
int x=q.front().x,y=q.front().y,dd=q.front().d;
if(x==x2 && y==y2)return dd;
q.pop();
for(int i=0;i<=3;++i){
int u=x+d[i][0];
int v=y+d[i][1];
if(map[u][v] && !vis[u][v]){
vis[u][v]=1;
q.push((point){u,v,dd+1});
}
}
}
return inf;
}
int start[M],nxt[M],to[M],w[M],e;
void add(int x, int y, int z){
to[++e]=y;
nxt[e]=start[x];
start[x]=e;
w[e]=z;
}
int f[N][N][4],cnt;
void pre(){
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
for(int k=0;k<=3;++k)
f[i][j][k]=++cnt;
int t;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
if(map[i][j])map[i][j]=0;else continue;
for(int k=0;k<=3;++k)
for(int l=0;l<=3;++l){
int x1=i+d[k][0],y1=j+d[k][1],x2=i+d[l][0],y2=j+d[l][1];
if(map[x1][y1] && map[x2][y2]){
t=bfs(x1,y1,x2,y2);
if(t<inf)add(f[i][j][k],f[x2][y2][l^1],t+1);
}
}
map[i][j]=1;
}
}
int p[M],dis[M];
int spfa(int s,int t){
queue<int>q;
for(int i=1;i<=cnt;++i)dis[i]=inf,p[i]=0;
p[s]=1;
q.push(s);
dis[s]=0;
while(!q.empty()){
int u=q.front();
p[u]=0;
q.pop();
for(int i=start[u];i;i=nxt[i]){
int v=to[i];
if(dis[v]>dis[u]+w[i]){
dis[v]=dis[u]+w[i];
if(!p[v])q.push(v);
p[v]=1;
}
}
}
return dis[t]<inf?dis[t]:-1;
}
int main(){
int x,y,x1,y1,x2,y2,t;
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
scanf("%d",&map[i][j]);
pre();
for(int i=1;i<=q;++i){
int S=++cnt,T=++cnt;
scanf("%d%d%d%d%d%d",&x,&y,&x1,&y1,&x2,&y2);
if(x1==x2 && y1==y2){
puts("0");continue;
}
if(!map[x1][y1] || !map[x2][y2]){
puts("-1");
continue;
}
map[x1][y1]=0;
//搜索出空格的移動狀態
for(int j=0;j<=3;++j){
int u=x1+d[j][0],v=y1+d[j][1];
if(map[u][v]){
int t=bfs(x, y, u, v);
if(t < inf)add(S, f[x1][y1][j], t);
}
}
map[x1][y1]=1;
for(int j=0;j<=3;++j){
int u=x2+d[j][0],v=y2+d[j][1];
if(map[u][v])add(f[x2][y2][j], T, 0);
}
printf("%d\n",spfa(S,T));
}
}