#include <bits/stdc++.h>
using namespace std;
const int INF = 2e9;
int dx[4] = {-1,+1,0,0};
int dy[4] = {0,0,-1,+1};
int h,w,L,q;
vector<vector<int>> mat;
namespace DSU
{
int father[300005], siz[300005];
pair<int, pair<int,int>> mxm[300005];
void init()
{
for(int i=1;i<=h*w;i++)
{
father[i] = i;
siz[i] = 1;
}
}
int get(int x)
{
if(father[x]!=x)
father[x]=get(father[x]);
return father[x];
}
void unite(int x, int y)
{
x = get(x);
y = get(y);
if(x == y)
return;
if(siz[x] < siz[y])
swap(x, y);
father[y] = x;
siz[x] += siz[y];
mxm[x] = max(mxm[x], mxm[y]);
}
}
int getid(int x, int y)
{
return (x-1) * w + y;
}
pair<int, pair<int,int>> nxt[300005][19];
vector<pair<int,pair<int,int>>> ord;
int qa[300005], qb[300005], qc[300005], qd[300005], lim[300005];
int who[300005];
vector<int> qrys[300005], comp[300005];
bool done[300005];
void uneste(int x, int y, int val)
{
x = who[x];
y = who[y];
if(x == y)
return;
if(comp[x].size() + qrys[x].size() < comp[y].size() + qrys[y].size())
swap(x, y);
for(int qid:qrys[y])
{
if((who[getid(qa[qid],qb[qid])] == x && who[getid(qc[qid],qd[qid])] == y) || (who[getid(qa[qid],qb[qid])] == y && who[getid(qc[qid],qd[qid])] == x))
{
assert(lim[qid] == INF);
lim[qid] = val;
done[qid] = 1;
}
else if(!done[qid])
qrys[x].push_back(qid);
}
for(int u:comp[y])
{
comp[x].push_back(u);
who[u] = x;
}
}
void calc_lim()
{
for(int i=1;i<=q;i++)
{
qrys[getid(qa[i],qb[i])].push_back(i);
qrys[getid(qc[i],qd[i])].push_back(i);
lim[i] = INF;
}
for(int i=1;i<=h*w;i++)
{
who[i] = i;
comp[i] = {i};
}
for(auto [val,poz]:ord)
{
int x = poz.first, y = poz.second;
for(int v=0;v<4;v++)
{
int newx = x + dx[v], newy = y + dy[v];
if(1<=newx && newx<=h && 1<=newy && newy<=w && mat[newx][newy] <= val)
{
uneste(getid(x,y), getid(newx,newy), val);
}
}
}
}
signed main()
{
ios_base::sync_with_stdio(0);cin.tie(0);
cin>>h>>w>>L;
mat.resize(h+2, vector<int>(w+2,0));
DSU::init();
for(int i=1;i<=h;i++)
{
for(int j=1;j<=w;j++)
{
cin>>mat[i][j];
ord.push_back({mat[i][j], {i,j}});
DSU::mxm[getid(i,j)] = {mat[i][j], {i,j}};
}
}
sort(ord.begin(), ord.end());
int poz = -1;
for(int i=0;i<ord.size();i++)
{
while(poz+1 < (int)ord.size() && ord[poz+1].first <= ord[i].first + L)
{
poz++;
for(int v=0;v<4;v++)
{
int x = ord[poz].second.first + dx[v];
int y = ord[poz].second.second + dy[v];
if(1<=x && x<=h && 1<=y && y<=w && mat[x][y] <= ord[poz].first)
DSU::unite(getid(x,y), getid(ord[poz].second.first, ord[poz].second.second));
}
}
assert(poz >= i);
int myid = getid(ord[i].second.first, ord[i].second.second);
nxt[myid][0] = DSU::mxm[DSU::get(myid)];
}
for(int p=1;p<19;p++)
for(int i=1;i<=h*w;i++)
nxt[i][p] = nxt[getid(nxt[i][p-1].second.first, nxt[i][p-1].second.second)][p-1];
cin>>q;
for(int i=1;i<=q;i++)
{
cin>>qa[i]>>qb[i]>>qc[i]>>qd[i];
}
calc_lim();
for(int i=1;i<=q;i++)
{
int a = qa[i], b = qb[i];
int rez = 0;
for(int p=18;p>=0;p--)
{
if(nxt[getid(a,b)][p].first < lim[i])
{
tie(a,b) = nxt[getid(a,b)][p].second;
rez += (1<<p);
}
}
if(nxt[getid(a,b)][0].first < lim[i])
cout<<-1<<"\n";
else
cout<<rez+1<<"\n";
}
return 0;
}