华容道
Time Limit: 1 Sec
Memory Limit: 128 MB
Submit: 34
Solved: 14
[ Submit][ Status][ Web Board]
Description
小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间。
小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:
1. 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1 个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的;
2. 有些棋子是固定的,有些棋子则是可以移动的;
3. 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。
游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。
给定一个棋盘,游戏可以玩 q 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第 i 次玩的时候,空白的格子在第 EXi 行第 EYi 列,指定的可移动棋子的初始位置为第 SXi 行第 SYi 列,目标位置为第 TXi 行第 TYi 列。
假设小 B 每秒钟能进行一次移动棋子的操作,而其他操作的时间都可以忽略不计。请
你告诉小 B 每一次游戏所需要的最少时间,或者告诉他不可能完成游戏。
Input
第一行有 3 个整数,每两个整数之间用一个空格隔开,依次表示 n、m 和 q;
接下来的 n 行描述一个 n*m 的棋盘,每行有 m 个整数,每两个整数之间用一个空格隔开,每个整数描述棋盘上一个格子的状态,0 表示该格子上的棋子是固定的,1 表示该格子上的棋子可以移动或者该格子是空白的。
接下来的 q 行,每行包含 6 个整数依次是 EXi、EYi、SXi、SYi、TXi、TYi,每两个整数之间用一个空格隔开,表示每次游戏空白格子的位置,指定棋子的初始位置和目标位置。
Output
输出有 q 行,每行包含 1 个整数,表示每次游戏所需要的最少时间,如果某次游戏无法完成目标则输出−1。
Sample Input
3 4 2
0 1 1 1
0 1 1 0
0 1 0 0
3 2 1 2 2 2
1 2 2 2 3 2
Sample Output
2
-1
HINT
【输入输出样例说明】
棋盘上划叉的格子是固定的,红色格子是目标位置,圆圈表示棋子,其中绿色圆圈表示目标棋子。
1.第一次游戏,空白格子的初始位置是 (3, 2)(图中空白所示),游戏的目标是将初始位置在(1, 2)上的棋子(图中绿色圆圈所代表的棋子)移动到目标位置(2, 2)(图中红色的格子)上。
2.第二次游戏,空白格子的初始位置是(1, 2)(图中空白所示),游戏的目标是将初始位置在(2, 2)上的棋子(图中绿色圆圈所示)移动到目标位置 (3, 2)上。
要将指定块移入目标位置,必须先将空白块移入目标位置,空白块要移动到目标位置,必然是从位置(2,2)上与当前图中目标位置上的棋子交换位置,之后能与空白块交换位置的只有当前图中目标位置上的那个棋子,因此目标棋子永远无法走到它的目标位置,游戏无法完成。
【数据范围】
对于 30%的数据,1 ≤ n, m ≤ 10,q = 1;
对于 60%的数据,1 ≤ n, m ≤ 30,q ≤ 10;
对于 100%的数据,1 ≤ n, m ≤ 30,q ≤ 500。
Source
题意:可以想象成首领之傲用R来拉箱子,要把箱子从初始位置拉到指定位置。能则输出最短步数,不能则输出 -1 。
题解:因为只有一个格子是空的,所以我们可以理解为将空白块移动到挨着指定块的位置,然后互换位置,有目的性地重复此操作,直到指定块归位。
首先我们可以想到利用搜索来解题,因为时间复杂度是O(p*n*m*n*m),即4*10^8,所以只好放弃。
这时候我们就想到了A*优化和最短路优化。
(p.s.,要看正解直接“page down”,看到“最短路”再停!)
A* : (不要着急说它是错的,虽然它的确是错的,不乐意看可以直接略过此处到最短路优化一节)很简单,照裸搜来写,然后把估价函数写好就行了。
首先bfs n*m次得出图中任意两点距离dist[][]。然后因为当指定块被空白块转换后,空白块需要至少两步才能到达指定块的另一侧,然后互换位置又是一步,所以我的估价函数写的是dist[a1][b1][x2][y2]*3+dist[a0][b0][a1][b1]即【指定块距离目标位置距离*3+空白块到被移动格子距离*1】。
而状态visit[a][b][c][d]记录的则是指定块在(a,b),空白快在(c,d)时的状态。
代码一60分(visit记录每个状态的最短移动距离)
(由于要省时间,这两个错了算法的代码都是手写堆,pq版删掉了)
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#define N 35
#define NN 1000
using namespace std;
struct Fiona
{
int f,w,x0,y0,x1,y1;
Fiona(int i1,int i2,int i3,int i4,int i5,int i6)
:f(i1),w(i2),x0(i3),y0(i4),x1(i5),y1(i6){}
Fiona(){}
};
struct Vayne
{
int x,y;
Vayne(int a,int b):x(a),y(b){}
};
int n,m,q,cnt;
int visit[N][N][N][N],block[N][N];
int dist[N][N][N][N];
int direct[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int x0,x1,x2;
int y0,y1,y2;
int eva(int a0,int b0,int a1,int b1)/*估价:空白块和指定块*/
{
return dist[a1][b1][x2][y2]*2+dist[a0][b0][a1][b1];
}
Fiona heap[NN*NN],c;
void insert(Fiona X)
{
int t=++cnt;
for(heap[t]=X;heap[t].f<heap[t>>1].f;t>>=1)c=heap[t],heap[t]=heap[t>>1],heap[t>>1]=c;
}
void pop()
{
int t=1,son;
for(heap[t]=heap[cnt--];(t<<1)<=cnt;t=son)
{
son=(t<<1==cnt||heap[t<<1].f<heap[t<<1|1].f)?t<<1:t<<1|1;
if(heap[son].f<heap[t].f)c=heap[t],heap[t]=heap[son],heap[son]=c;
else break;
}
}
void priority_bfs()
{
int i,j,vx,vy,x,y,w,cx,cy;
scanf("%d%d%d%d%d%d",&x0,&y0,&x1,&y1,&x2,&y2);
if(x1==x2&&y1==y2)
{
printf("0\n");
return ;
}
if(dist[x0][y0][x1][y1]>NN*NN||dist[x1][y1][x2][y2]>NN*NN)
{
printf("-1\n");
return ;
}
cnt=0;
memset(visit,0x11,sizeof(visit));
Fiona U(eva(x0,y0,x1,y1),0,x0,y0,x1,y1);
visit[x1][y1][x0][y0]=0;
insert(U);
while(cnt)
{
U=heap[1];
pop();
w=U.w+1;
x=U.x0;
y=U.y0;
cx=U.x1;
cy=U.y1;
for(i=0;i<4;i++)
{
vx=x+direct[i][0];
vy=y+direct[i][1];
if(!block[vx][vy])continue;
if(vx==cx&&vy==cy)
{
if(visit[x][y][cx][cy]>w)
{
if(x==x2&&y==y2)
{
printf("%d\n",w);
return ;
}
visit[x][y][cx][cy]=w;
insert(Fiona(eva(cx,cy,x,y)+w,w,cx,cy,x,y));
}
}
else if(visit[cx][cy][vx][vy]>w)
{
visit[cx][cy][vx][vy]=w;
insert(Fiona(eva(vx,vy,cx,cy)+w,w,vx,vy,cx,cy));
}
}
}
printf("-1\n");
}
void prepare()
{
int i,j,k,x,y,vx,vy;
Vayne U(0,0);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
queue<Vayne>q;
q.push(Vayne(i,j));
dist[i][j][i][j]=0;
while(!q.empty())
{
U=q.front();
q.pop();
x=U.x;
y=U.y;
for(k=0;k<4;k++)
{
vx=x+direct[k][0];
vy=y+direct[k][1];
if(dist[i][j][vx][vy]>1000&&block[vx][vy])
{
dist[i][j][vx][vy]=dist[i][j][x][y]+1;
q.push(Vayne(vx,vy));
}
}
}
}
}
}
int main()
{
freopen("puzzle.in","r",stdin);
freopen("puzzle.ans","w",stdout);
memset(dist,0x11,sizeof(dist));
int i,j;
scanf("%d%d%d",&n,&m,&q);
for(i=1;i<=n;i++)for(j=1;j<=m;j++)
{
scanf("%d",&block[i][j]);
}
prepare();
for(i=1;i<=q;i++)
{
priority_bfs();
}
return 0;
}
呵呵,20个点只过了前12个,60分。
代码二60分(visit记录是否到过某个状态,这个有明显缺陷,因为有的状态对,即两个状态间可能估价小的实际距离大,所以不能保证第一次搜到某个状态就是最优~)
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#define N 35
#define NN 1000
using namespace std;
struct Fiona
{
int f,w,x0,y0,x1,y1;
Fiona(int i1,int i2,int i3,int i4,int i5,int i6)
:f(i1),w(i2),x0(i3),y0(i4),x1(i5),y1(i6){}
Fiona(){}
};
struct Vayne
{
int x,y;
Vayne(int a,int b):x(a),y(b){}
};
int n,m,q,cnt;
int visit[N][N][N][N],block[N][N];
int dist[N][N][N][N];
int direct[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int x0,x1,x2;
int y0,y1,y2;
int eva(int a0,int b0,int a1,int b1)/*估价:空白格和被动格*/
{
return dist[a1][b1][x2][y2]*3+dist[a0][b0][a1][b1];
}
Fiona heap[NN*NN],c;
void insert(Fiona X)
{
int t=++cnt;
for(heap[t]=X;heap[t].f<heap[t>>1].f;t>>=1)c=heap[t],heap[t]=heap[t>>1],heap[t>>1]=c;
}
void pop()
{
int t=1,son;
for(heap[t]=heap[cnt--];(t<<1)<=cnt;t=son)
{
son=(t<<1==cnt||heap[t<<1].f<heap[t<<1|1].f)?t<<1:t<<1|1;
if(heap[son].f<heap[t].f)c=heap[t],heap[t]=heap[son],heap[son]=c;
else break;
}
}
void priority_bfs(int cases)
{
int i,vx,vy,x,y,w,cx,cy;
scanf("%d%d%d%d%d%d",&x0,&y0,&x1,&y1,&x2,&y2);
if(x1==x2&&y1==y2)
{
printf("0\n");
return ;
}
if(dist[x0][y0][x1][y1]>NN*NN||dist[x1][y1][x2][y2]>NN*NN)
{
printf("-1\n");
return ;
}
cnt=0;
Fiona U(eva(x0,y0,x1,y1),0,x0,y0,x1,y1);
visit[x1][y1][x0][y0]=cases;
insert(U);
while(cnt)
{
U=heap[1];
pop();
w=U.w+1;
x=U.x0;
y=U.y0;
cx=U.x1;
cy=U.y1;
for(i=0;i<4;i++)
{
vx=x+direct[i][0];
vy=y+direct[i][1];
if(!block[vx][vy])continue;
if(vx==cx&&vy==cy)
{
if(visit[x][y][cx][cy]!=cases)
{
if(x==x2&&y==y2)
{
printf("%d\n",w);
return ;
}
visit[x][y][cx][cy]=cases;
insert(Fiona(eva(cx,cy,x,y)+w,w,cx,cy,x,y));
}
}
else if(visit[cx][cy][vx][vy]!=cases)
{
visit[cx][cy][vx][vy]=cases;
insert(Fiona(eva(vx,vy,cx,cy)+w,w,vx,vy,cx,cy));
}
}
}
printf("-1\n");
}
void prepare()
{
int i,j,k,x,y,vx,vy;
Vayne U(0,0);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
queue<Vayne>q;
q.push(Vayne(i,j));
dist[i][j][i][j]=0;
while(!q.empty())
{
U=q.front();
q.pop();
x=U.x;
y=U.y;
for(k=0;k<4;k++)
{
vx=x+direct[k][0];
vy=y+direct[k][1];
if(dist[i][j][vx][vy]>1000&&block[vx][vy])
{
dist[i][j][vx][vy]=dist[i][j][x][y]+1;
q.push(Vayne(vx,vy));
}
}
}
}
}
}
int main()
{
freopen("puzzle.in","r",stdin);
freopen("puzzle.ans","w",stdout);
memset(dist,0x11,sizeof(dist));
int i,j;
scanf("%d%d%d",&n,&m,&q);
for(i=1;i<=n;i++)for(j=1;j<=m;j++)
{
scanf("%d",&block[i][j]);
}
prepare();
for(i=1;i<=q;i++)
{
priority_bfs(i);
}
return 0;
}
这个更呵呵了,同样过了前12个点,60分,但是还有WA的。
打击人的是代码三70分(不要A*的裸搜,同学写的):
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
using namespace std;
struct state
{
int space_x,space_y,son_x,son_y,step;
state(){space_x=space_y=son_x=son_y=step=0;}
};
bool hash[31][31][31][31];
int map[101][101];
int main()
{
freopen("puzzle.in","r",stdin);
freopen("puzzle.ans","w",stdout);
register int i,j;
int n,m,t;
scanf("%d%d%d",&n,&m,&t);
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
scanf("%d",&map[i][j]);
queue<state> q;
while(t--)
{
memset(hash , 0 , sizeof(hash));
int s_x,s_y,b_x,b_y,e_x,e_y;
scanf("%d%d%d%d%d%d",&s_x,&s_y,&b_x,&b_y,&e_x,&e_y);
hash[s_x][s_y][b_x][b_y] = 1;
state begin;
begin.space_x=s_x;
begin.space_y=s_y;
begin.son_x=b_x;
begin.son_y=b_y;
begin.step=0;
q.push(begin);
bool find=0;
while(!q.empty())
{
state ins=q.front();
q.pop();
if(ins.son_x==e_x&&ins.son_y==e_y)
{
printf("%d\n",ins.step);
find=1;
break;
}
for(i=0;i<4;++i)
{
int tx=ins.space_x+dx[i];
int ty=ins.space_y+dy[i];
if((tx!=ins.son_x||ty!=ins.son_y)&&tx>=1&&tx<=n&&ty>=1&&ty<=m)
{
if((tx!=ins.son_x||ty!=ins.son_y)&&map[tx][ty])
if(!hash[tx][ty][ins.son_x][ins.son_y])
{
hash[tx][ty][ins.son_x][ins.son_y] = 1;
state tmp;
tmp.space_x=tx;
tmp.space_y=ty;
tmp.son_x=ins.son_x;
tmp.son_y=ins.son_y;
tmp.step=ins.step+1;
q.push(tmp);
}
}
}
if(abs(ins.space_x-ins.son_x)+abs(ins.space_y-ins.son_y)==1)
{
int tx=ins.space_x;
int ty=ins.space_y;
if(!hash[ins.son_x][ins.son_y][tx][ty])
{
hash[ins.son_x][ins.son_y][tx][ty] = 1;
state tmp;
tmp.space_x=ins.son_x;
tmp.space_y=ins.son_y;
tmp.son_x=tx;
tmp.son_y=ty;
tmp.step=ins.step+1;
q.push(tmp);
}
}
}
if(!find) printf("-1\n");
q = queue<state>();
}
return 0;
}
这个代码70分,分析一下,是因为A*有个log级别维护最值的常数,所以反而慢了些(不要着急反驳说还有更多的原因)
真正让我放弃A*的是当我把估价函数写成return 0时,代码竟然变快了?!!于是我就开始认真分析A*的优劣了。
总结:A*适合冗余状态较多(,估价函数好写)的搜索,这样可以删减去很多没用的搜索(搜索方向),这一切,盖因它是一种有目的性,或者说有方向性的搜索,而估价函数赋予了它这种方向性。同时有一个小总结就是,A*需要:在最优路径上,每个状态的估价函数值需要保持非严格递增(当然严格更好),否则若在最优路径上估价函数值是波动的,则可能走错方向,导致反而增添了许多冗余的搜索!于是,这题还写搜索?还写A*?还写双向BFS?见鬼去吧,最短路才可以拯救你。
最短路:这道题的图其实是一张n*m的图,动态加障碍(指定块),然后bfs搜索转移状态,所以我们完全可以预处理一遍,加边,然后跑最短路。
那么该如何加边呢?
啊,很简单,不要想太难。两个比较有用的状态之间加容易加的边就好了。什么叫有用的状态呢?就是一个“空白块挨着指定块”状态!
此题加的边为一个 “有用状态” 到一个指定块与其相邻的 “有用状态” ,然后每次询问连源连汇,万事大吉。
附代码,不懂自己看,或者手调,不是很难理解。
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define N 35
#define NN 7000
#define M 25000
#define inf 0x3f3f3f3f
using namespace std;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct Syndra
{
int u,v,len,next;
}e[M];
struct Fiona
{
int x,y;
Fiona(int a,int b):x(a),y(b){}
Fiona(){}
};
struct Vayne
{
int f,v;
Vayne(int a,int b):f(a),v(b){}
Vayne(){}
bool operator < (const Vayne& a)const
{return a.f<f;}
};
int head[NN],id[N][N][N],cnt,num;
int map[N][N];
int n,m,query;
queue<Fiona>q;
queue<int>Q;
priority_queue<Vayne> pq;
int dis[N][N],dist[NN],in[NN];
void add(int u,int v,int len)
{
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].len=len;
e[cnt].next=head[u];
head[u]=cnt;
}
int bfs(int sx,int sy,int tx,int ty)/*已检查,绝对正确*/
{
int i,vx,vy;
if(sx==tx&&sy==ty)return 0;
if(!map[sx][sy]||!map[tx][ty])return inf;
while(!q.empty())q.pop();
memset(dis,0x3f,sizeof(dis));
q.push(Fiona(sx,sy));
dis[sx][sy]=0;
while(!q.empty())
{
Fiona U=q.front();
q.pop();
for(i=0;i<4;i++)
{
vx=U.x+dir[i][0];
vy=U.y+dir[i][1];
if(dis[vx][vy]>dis[U.x][U.y]+1&&map[vx][vy])
{
dis[vx][vy]=dis[U.x][U.y]+1;
if(vx==tx&&vy==ty)return dis[vx][vy];
q.push(Fiona(vx,vy));
}
}
}
return inf;
}
int pqspfa(int s,int t)
{
int i,u,v;
Vayne X;
memset(dist,0x3f,sizeof(dist));
memset(in,0,sizeof(in));
while(!pq.empty())pq.pop();
pq.push(Vayne(0,s));
dist[s]=0;
in[s]=1;
while(!pq.empty())
{
X=pq.top();
pq.pop();
u=X.v;
in[u]=0;
for(i=head[u];i;i=e[i].next)
{
v=e[i].v;
if(dist[v]>dist[u]+e[i].len)
{
dist[v]=dist[u]+e[i].len;
if(!in[v])pq.push(Vayne(dist[v],v)),in[v]=1;
}
}
}
return dist[t]<inf?dist[t]:-1;
}
int spfa(int s,int t)/*已检查,绝对正确*/
{
int i,u,v;
memset(dist,0x3f,sizeof(dist));
memset(in,0,sizeof(in));
while(!Q.empty())Q.pop();
Q.push(s);
dist[s]=0;
in[s]=1;
while(!Q.empty())
{
u=Q.front();
Q.pop();
in[u]=0;
for(i=head[u];i;i=e[i].next)
{
v=e[i].v;
if(dist[v]>dist[u]+e[i].len)
{
dist[v]=dist[u]+e[i].len;
if(!in[v])Q.push(v),in[v]=1;
}
}
}
return dist[t]<inf?dist[t]:-1;
}
void build()/*已检查,绝对正确*/
{
int i,j,k,l,i1,j1,i2,j2;
int temp;
scanf("%d%d%d",&n,&m,&query);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
for(k=0;k<4;k++)id[i][j][k]=++num;
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)if(map[i][j])
{
map[i][j]=0;
for(k=0;k<4;k++)if(map[i1=i+dir[k][0]][j1=j+dir[k][1]])
{
for(l=k;l<4;l++)if(map[i2=i+dir[l][0]][j2=j+dir[l][1]])
{
temp=bfs(i1,j1,i2,j2)+1;
if(temp<inf)
{
add(id[i][j][k],id[i2][j2][l^1],temp);
if(k!=l)add(id[i][j][l],id[i1][j1][k^1],temp);
}
}
}
map[i][j]=1;
}
}
/*上为优化,下为标程*/
/*
int move[N][N][N][N];
memset(move,0x3f,sizeof(move));
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)if(map[i][j])
{
map[i][j]=0;
for(k=0;k<4;k++)if(map[i1=i+dir[k][0]][j1=j+dir[k][1]])
{
for(l=0;l<4;l++)if(map[i2=i+dir[l][0]][j2=j+dir[l][1]])
{
move[i][j][k][l]=bfs(i1,j1,i2,j2)+1;
}
}
map[i][j]=1;
}
}
for(i=1;i<=n;i++)for(j=1;j<=m;j++)
{
for(k=0;k<4;k++)for(l=0;l<4;l++)
{
if(move[i][j][k][l]<inf)add(id[i][j][k],id[i+dir[l][0]][j+dir[l][1]][l^1],move[i][j][k][l]);
}
}
*/
}
void handle()/*已检查:绝对正确*/
{
int i,s,t;
int vx,vy,temp;
int bx,by,sx,sy,tx,ty;
while(query--)
{
scanf("%d%d%d%d%d%d",&bx,&by,&sx,&sy,&tx,&ty);
if(sx==tx&&sy==ty)
{
printf("0\n");
continue;
}
if(!map[sx][sy]||!map[tx][ty])
{
printf("-1\n");
continue;
}
s=++num;
t=++num;
map[sx][sy]=0;
for(i=0;i<4;i++)
{
vx=sx+dir[i][0];
vy=sy+dir[i][1];
if(!map[vx][vy])continue;
temp=bfs(bx,by,vx,vy);
if(temp<inf)add(s,id[sx][sy][i],temp);
}
map[sx][sy]=1;
for(i=0;i<4;i++)if(map[tx+dir[i][0]][ty+dir[i][1]])add(id[tx][ty][i],t,0);
printf("%d\n",spfa(s,t));
}
}
int main()/*这里不需要检查*/
{
freopen("puzzle.in","r",stdin);
freopen("puzzle.ans","w",stdout);
build();
handle();
return 0;
}
另:这道题略坑,“卡优化”,上面代码spfa 0.84秒20组数据完成,pqspfa?1.6s+!
这里还有一个删节版,就是把没用的都删掉了
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define N 35
#define NN 7000
#define M 25000
#define inf 0x3f3f3f3f
using namespace std;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct Syndra
{
int u,v,len,next;
}e[M];
struct Fiona
{
int x,y;
Fiona(int a,int b):x(a),y(b){}
Fiona(){}
};
int head[NN],id[N][N][N],cnt,num;
int map[N][N];
int n,m,query;
queue<Fiona>q;
queue<int>Q;
int dis[N][N],dist[NN],in[NN];
void add(int u,int v,int len)
{
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].len=len;
e[cnt].next=head[u];
head[u]=cnt;
}
int bfs(int sx,int sy,int tx,int ty)
{
int i,vx,vy;
if(sx==tx&&sy==ty)return 0;
if(!map[sx][sy]||!map[tx][ty])return inf;
while(!q.empty())q.pop();
memset(dis,0x3f,sizeof(dis));
q.push(Fiona(sx,sy));
dis[sx][sy]=0;
while(!q.empty())
{
Fiona U=q.front();
q.pop();
for(i=0;i<4;i++)
{
vx=U.x+dir[i][0];
vy=U.y+dir[i][1];
if(dis[vx][vy]>dis[U.x][U.y]+1&&map[vx][vy])
{
dis[vx][vy]=dis[U.x][U.y]+1;
if(vx==tx&&vy==ty)return dis[vx][vy];
q.push(Fiona(vx,vy));
}
}
}
return inf;
}
int spfa(int s,int t)
{
int i,u,v;
memset(dist,0x3f,sizeof(dist));
memset(in,0,sizeof(in));
while(!Q.empty())Q.pop();
Q.push(s);
dist[s]=0;
in[s]=1;
while(!Q.empty())
{
u=Q.front();
Q.pop();
in[u]=0;
for(i=head[u];i;i=e[i].next)
{
v=e[i].v;
if(dist[v]>dist[u]+e[i].len)
{
dist[v]=dist[u]+e[i].len;
if(!in[v])Q.push(v),in[v]=1;
}
}
}
return dist[t]<inf?dist[t]:-1;
}
void build()
{
int i,j,k,l,i1,j1,i2,j2;
int temp;
scanf("%d%d%d",&n,&m,&query);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
for(k=0;k<4;k++)id[i][j][k]=++num;
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)if(map[i][j])
{
map[i][j]=0;
for(k=0;k<4;k++)if(map[i1=i+dir[k][0]][j1=j+dir[k][1]])
{
for(l=k;l<4;l++)if(map[i2=i+dir[l][0]][j2=j+dir[l][1]])
{
temp=bfs(i1,j1,i2,j2)+1;
if(temp<inf)
{
add(id[i][j][k],id[i2][j2][l^1],temp);
if(k!=l)add(id[i][j][l],id[i1][j1][k^1],temp);
}
}
}
map[i][j]=1;
}
}
}
void handle()
{
int i,s,t;
int vx,vy,temp;
int bx,by,sx,sy,tx,ty;
while(query--)
{
scanf("%d%d%d%d%d%d",&bx,&by,&sx,&sy,&tx,&ty);
if(sx==tx&&sy==ty)
{
printf("0\n");
continue;
}
if(!map[sx][sy]||!map[tx][ty])
{
printf("-1\n");
continue;
}
s=++num;
t=++num;
map[sx][sy]=0;
for(i=0;i<4;i++)
{
vx=sx+dir[i][0];
vy=sy+dir[i][1];
if(!map[vx][vy])continue;
temp=bfs(bx,by,vx,vy);
if(temp<inf)add(s,id[sx][sy][i],temp);
}
map[sx][sy]=1;
for(i=0;i<4;i++)if(map[tx+dir[i][0]][ty+dir[i][1]])add(id[tx][ty][i],t,0);
printf("%d\n",spfa(s,t));
}
}
int main()
{
build();
handle();
return 0;
}