#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pii pair<int, int>
#define all(a) a.begin(), a.end()
using namespace std;
#ifdef LOCAL
#include "C:\Users\Dell\Downloads\template\template\icpc-notebook\Utilities\debug.h"
#else
#define debug(...) 42
#endif
const int mn = 2e6 + 5, mod = 1e9 + 7, inf = 2e9;
int n, m, l, cnt;
vector <vector <int>> a;
vector <pii> mov = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
bool check(int x, int y) {
return x >= 1 && x <= m && y >= 1 && y <= n;
}
int convert(int x, int y) {
return n * (x - 1) + y;
}
int par_[mn], val[mn], d[mn], st[mn], ft[mn], euler[mn], timer_dfs = 0, up[mn][20], lg2[mn];
vector <int> adj[mn], nxt[mn];
void dfs(int u) {
st[u] = ++ timer_dfs; euler[timer_dfs] = u;
for(auto v : adj[u]) {
d[v] = d[u] + 1;
dfs(v);
euler[++ timer_dfs] = u;
}
ft[u] = timer_dfs;
}
int higher(int u, int v) {
return (d[u] < d[v] ? u : v);
}
void build() {
for(int i = 1; i <= timer_dfs; i++) up[i][0] = euler[i];
for(int j = 1; (1 << j) <= timer_dfs; j++) {
for(int i = 1; i <= timer_dfs; i++) {
up[i][j] = higher(up[i][j - 1], up[i + (1 << (j - 1))][j - 1]);
}
}
lg2[0] = -1;
for(int i = 1; i <= timer_dfs; i++) lg2[i] = lg2[i >> 1] + 1;
}
int lca(int u, int v) {
int l = st[u], r = st[v];
if(l > r) swap(l, r);
int kc = lg2[r - l + 1];
return higher(up[l][kc], up[r - (1 << kc) + 1][kc]);
}
int kc(int u, int v) {
return val[lca(u, v)];
}
void init() {
cnt = m * n;
for(int i = 1; i <= m * n; i++) par_[i] = i;
}
int find(int u) {
if(u == par_[u]) return u;
return par_[u] = find(par_[u]);
}
void join(int u, int v, int w) {
u = find(u), v = find(v);
if(u == v) return;
cnt ++;
par_[u] = par_[v] = par_[cnt] = cnt;
adj[cnt].push_back(u);
adj[cnt].push_back(v);
val[cnt] = w;
}
int ans[3005][3005];
void solve() {
cin >> m >> n >> l;
a.resize(m + 1, vector <int> (n + 1));
for(int i = 1; i <= m; i++) {
for(int j = 1; j <= n; j++) {
cin >> a[i][j];
val[convert(i, j)] = a[i][j];
}
}
vector <array<int, 3>> edge;
for(int i = 1; i <= m; i++) {
for(int j = 1; j <= n; j++) {
for(auto [di, dj] : mov) {
int ni = i + di, nj = j + dj;
if(check(ni, nj)) {
edge.push_back({max(a[i][j], a[ni][nj]), convert(i, j), convert(ni, nj)});
}
}
}
}
sort(all(edge));
init();
for(auto [w, u, v] : edge) join(u, v, w);
dfs(cnt); build();
int q; cin >> q;
if(m * n <= 3000) {
for(int i = 1; i <= m * n; i++) {
for(int j = i + 1; j <= m * n; j++) {
if(kc(i, j) <= val[i] + l) nxt[i].push_back(j);
if(kc(i, j) <= val[j] + l) nxt[j].push_back(i);
}
}
for(int i = 1; i <= m * n; i++) {
for(int j = 1; j <= m * n; j++) {
ans[i][j] = inf;
}
ans[i][i] = 0;
queue <int> q;
q.push(i);
while(q.size()) {
int u = q.front();
q.pop();
for(auto v : nxt[u]) {
if(ans[i][v] > ans[i][u] + 1) {
ans[i][v] = ans[i][u] + 1;
q.push(v);
}
}
}
}
while(q--) {
int x, y, u, v; cin >> x >> y >> u >> v;
int a_ = convert(x, y), b_ = convert(u, v);
if(ans[a_][b_] != inf) cout << ans[a_][b_] << '\n';
else cout << -1 << '\n';
}
}
}
signed main(){
ios_base::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
#define task "Kawabata"
if (fopen(task".INP", "r")) {
freopen(task".INP", "r", stdin);
freopen(task".OUT", "w", stdout);
}
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}
// Don't wanna lose anymore T_T
// Never let me go - Kazuo Ishiguro