/*
ROAD TO TST
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define fi first
#define se second
#define pii pair<int, int>
#define el "\n"
#define pb push_back
#define all(v) v.begin(), v.end()
#define rep(i, x, y) for(int i = x, _y = y; i <= _y; i++)
#define rev(i, x, y) for(int i = x, _y = y; i >= _y; i--)
void file() {
#define name "test"
if(fopen(name".inp", "r")) {freopen(name".inp", "r", stdin);freopen(name".out", "w", stdout);}
else {
#undef name
#define name "C:\\Users\\hminh\\Desktop\\2026\\AIO\\test"
if(fopen(name".inp", "r")) {freopen(name".inp", "r", stdin);freopen(name".out", "w", stdout);}
}
}
const int nmax = 6e5 + 7;
int n, m, q, L;
vector<vector<int>> a, nx[19];
int dx[] = {0, 0, -1, 1}, dy[] = {1, -1, 0, 0};
int par[nmax], maxx[nmax], val[nmax], up[19][nmax], h[nmax];
vector<int> g[nmax];
struct edge {
int u, v, w;
edge(int _u = 0, int _v = 0, int _w = 0) {
u = _u, v = _v, w = _w;
}
};
bool cmp(edge a, edge b) {
return a.w == b.w ? a.v > b.v : a.w < b.w;
}
vector<edge> E;
int find_par(int u) {
return u == par[u] ? u : par[u] = find_par(par[u]);
}
void construct() {
int cur = n * m - 1;
rep(i, 0, 2 * n * m - 1) par[i] = i;
for(edge e : E) {
int u = e.u, v = e.v;
u = find_par(u), v = find_par(v);
if(u == v) continue;
cur++;
val[cur] = e.w;
g[cur].pb(u), g[cur].pb(v);
par[u] = par[v] = cur;
}
}
void dfs(int u) {
for(int v : g[u]) {
up[0][v] = u;
h[v] = h[u] + 1;
rep(i, 1, 18) {
if((1 << i) > h[v]) continue;
up[i][v] = up[i - 1][up[i - 1][v]];
}
dfs(v);
}
}
int lca(int u, int v) {
if(h[u] < h[v]) swap(u, v);
int k = h[u] - h[v];
rev(i, 18, 0) {
if(k >> i & 1) u = up[i][u];
}
if(u == v) return u;
rev(i, 18, 0) {
if(up[i][u] != up[i][v]) u = up[i][u], v = up[i][v];
}
return up[0][u];
}
void build_krt() {
rep(i, 0, n - 1) {
rep(j, 0, m - 1) {
rep(p, 0, 3) {
int x = i + dx[p], y = j + dy[p];
if(x < 0 || y < 0 || x >= n || y >= m) continue;
E.pb(edge(i * m + j, x * m + y, max(a[i][j], a[x][y])));
}
}
}
sort(all(E), cmp);
construct();
dfs(2 * n * m - 2);
}
int pos[nmax];
void union_sets(int u, int v) {
u = find_par(u), v = find_par(v);
if(u == v) return;
par[v] = u;
if(maxx[u] < maxx[v]) pos[u] = pos[v];
maxx[u] = max(maxx[u], maxx[v]);
}
void build_next() {
rep(k, 0, 18) {
nx[k].resize(n);
rep(i, 0, n - 1) nx[k][i].resize(m, 0);
}
rep(i, 0, n * m - 1) par[i] = i, maxx[i] = a[i / m][i % m], pos[i] = i;
rep(i, 0, n - 1) {
rep(j, 0, m - 1) {
E.pb(edge(i * m + j, 1, a[i][j]));
E.pb(edge(i * m + j, -1, a[i][j] + L));
}
}
sort(all(E), cmp);
for(edge e : E) {
int id = e.u, t = e.v, w = e.w;
int i = id / m, j = id % m;
if(t == 1) {
rep(p, 0, 3) {
int x = i + dx[p], y = j + dy[p];
if(x < 0 || y < 0 || x >= n || y >= m || a[x][y] > w) continue;
union_sets(id, x * m + y);
// cout << i << ' ' << j << ' ' << x << ' ' << y << el;
}
}
else {
int idx = pos[find_par(id)];
nx[0][i][j] = idx;
}
}
rep(k, 1, 18) rep(i, 0, n - 1) rep(j, 0, m - 1) {
int id = nx[k - 1][i][j];
nx[k][i][j] = nx[k - 1][id / m][id % m];
}
}
int main()
{
file();
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> n >> m >> L;
a.resize(n);
rep(i, 0, n - 1) {
a[i].resize(m);
rep(j, 0, m - 1) cin >> a[i][j];
}
build_krt();
E.clear();
build_next();
cin >> q;
while(q -- ) {
int x, y, u, v;
cin >> x >> y >> u >> v;
x--,y--,u--,v--;
int h = val[lca(x * m + y, u * m + v)], res = 0;
rev(k, 18, 0) {
int id = nx[k][x][y], i = id / m, j = id % m;
if(a[i][j] < h) {
res += 1 << k;
x = i, y = j;
}
}
// cout << h << ' ' << res << ' ' << x << ' ' << y << ' ' << a[x][y] << el;
if(a[x][y] >= h - L) cout << res + 1;
else cout << -1;
cout << el;
}
return 0;
}