#include<fstream>
#define Nmax 100100
#define M 310
#include<vector>
#include<algorithm>
using namespace std;
ifstream f("matrice2.in");
ofstream g("matrice2.out");
int dx[]={0,0,0,-1,1};
int dy[]={0,-1,1,0,0};
vector<int> v[Nmax];
struct cel{ int k,p;}V[Nmax];
struct que{ int a,b,st,dr,ind;}q[Nmax];
int dpa( que A,que B ){return A.a<B.a;};
int dpi( que A,que B ){return A.ind<B.ind;};
int dpk( cel A,cel B ){return A.k<B.k;};
int i,n,m,T[Nmax],N,val,k,t1,x,ic,jc,t2,t,vm,po,R[Nmax],xc,A[M][M],j,yc,xu,yu;
void unite(int x,int y)
{
if(R[x]<=R[y])
{
T[x]=y;
if(R[x]==R[y])
R[y]++;
}
else
T[y]=x;
}
int find(int x)
{
int aux=x;
while(x!=T[x])
x=T[x];
int taso=x;
x=aux;
while(x!=taso)
{
aux=T[x];
T[x]=taso;
x=aux;
}
return taso;
}
int main ()
{
f>>n>>m;
for(i=1;i<=n;++i)
for(j=1;j<=n;++j)
{
f>>V[(i-1)*n+j].k;
V[(i-1)*n+j].p=(i-1)*n+j;
A[i][j]=(i-1)*n+j;
}
for(i=1;i<=n;++i)
for(j=1;j<=n;++j)
for(k=1;k<=4;++k)
{
ic=i+dx[k];
jc=j+dy[k];
if(ic<1||jc<1||ic>n||jc>n)
continue;
v[A[i][j]].push_back(A[ic][jc]);
}
N=n*n;
sort(V+1,V+N+1,dpk);
for(i=1;i<=m;++i)
{
f>>xu>>yu>>xc>>yc;
q[i].st=A[xu][yu];
q[i].dr=A[xc][yc];
q[i].ind=i;
q[i].b=V[N].k+1;
}
vm=V[N].k;
for(po=1;po<=vm;po<<=1);
po>>=1;
for(;po;po>>=1)
{
j=1;
sort(q+1,q+m+1,dpa);
for(i=1;i<=N;++i)
R[i]=1,T[i]=i;
for(i=1;i<=m;++i)
{
val=q[i].a+po;
for(;j<=N;++j)
{
if(V[j].k>val)
break;
x=V[j].p;
t1=find(x);
for(t=0;t<v[x].size();++t)
{
if(j==4)
{
j++;
j--;
}
if(V[v[x][t]].k>val)
continue;
t2=find(v[x][t]);
if(t2!=t1)
unite(t1,t2);
}
}
if(po==4&&i==m)
{
i++;
i--;
}
t1=find(q[i].st);
t2=find(q[i].dr);
if(t1!=t2)
q[i].a+=po;
else
q[i].b=min(q[i].b,q[i].a+po);
}
if(x==x)
{
x++;
x--;
}
}
sort(q+1,q+m+1,dpi);
for(i=1;i<=m;++i)
g<<q[i].b<<"\n";
return 0;
}