#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
struct uf{
int n;
vector<int> par;
uf(int n_):n(n_), par(n_, -1){}
int root(int a){
return par[a] <= -1 ? a : par[a] = root(par[a]);
}
bool same(int a, int b){
return root(a) == root(b);
}
int unite(int a, int b, bool opt = false){
a = root(a);
b = root(b);
if (a == b) return 0;
if (opt && par[a] > par[b]) swap(a, b);
par[a] += par[b];
par[b] = a;
return 1;
}
};
vector<int> solve(int H, int W, int L, vector<vector<int>> &T, int Q, vector<int> &A, vector<int> &B, vector<int> &C, vector<int> &D){
rep(i, 0, Q){
A[i]--, B[i]--, C[i]--, D[i]--;
}
struct pos{
int x;
int y;
};
auto get_ind =[&](pos a) -> int {
return a.x * W + a.y;
};
auto get_T = [&](pos a) -> int {
return T[a.x][a.y];
};
vector<int> dx = {1, -1, 0, 0};
vector<int> dy = {0, 0, 1, -1};
// 1日で、どこまでいけるかを判定する
const int X = 19;
vector to(X, vector<int>(H * W));
vector<pair<pos, int>> order;
vector<vector<int>> lis(H * W);
{
uf U(H * W);
vector seen(H, vector<int>(W));
rep(i, 0, H) rep(j, 0, W){
order.push_back({{i, j}, T[i][j] + L});
order.push_back({{i, j}, T[i][j]});
}
sort(order.begin(), order.end(), [&](pair<pos, int> l, pair<pos, int> r){
if (l.second != r.second) return l.second < r.second;
return get_T(l.first) == l.second && get_T(r.first) != r.second;
});
for (auto [a, b] : order){
if (get_T(a) == b){
rep(k, 0, 4){
pos tmp = {a.x + dx[k], a.y + dy[k]};
if (tmp.x < 0 || tmp.y < 0 || H <= tmp.x || W <= tmp.y) continue;
if (seen[tmp.x][tmp.y]){
if (U.unite(get_ind(a), get_ind(tmp))){
lis[get_ind(a)].push_back(get_ind(tmp));
}
}
}
seen[a.x][a.y] = 1;
}
else{
to[0][get_ind(a)] = U.root(get_ind(a));
}
}
}
// ダブリングの元を構築
{
rep(d, 1, X) rep(i, 0, H * W){
to[d][i] = to[d - 1][to[d - 1][i]];
}
}
// 並列二分探索を行う
vector<int> ans(Q, 1);
vector<pos> p(Q);
rep(i, 0, Q) p[i] = {A[i], B[i]};
for (int d = X - 1; d >= -1; d--){
vector<vector<int>> G(H * W);
uf U(H * W);
rep(i, 0, Q){
if (d != -1) G[to[d][get_ind(p[i])]].push_back(i);
else G[get_ind(p[i])].push_back(i);
}
rep(rp, 0, H * W * 2){
auto [a, b] = order[rp];
for (auto x : lis[get_ind(a)]) U.unite(get_ind(a), x, true);
if (get_T(a) != b){
for (auto id : G[get_ind(a)]){
if (!U.same(get_ind(a), get_ind({C[id], D[id]}))){
p[id] = a;
if (d != -1) ans[id] += (1 << d);
else ans[id]++;
}
}
}
}
}
// 出力
for (auto &x : ans) if (x >= (1 << X)) x = -1;
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int H, W, L;
cin >> H >> W >> L;
int sw = 0;
// if (H > W) swap(H, W), sw = 1;
vector T(H, vector<int>(W));
if (sw) rep(i, 0, W) rep(j, 0, H){
cin >> T[j][i];
}
else rep(i, 0, H) rep(j, 0, W) {
cin >> T[i][j];
}
int Q;
cin >> Q;
vector<int> A(Q), B(Q), C(Q), D(Q);
rep(i, 0, Q){
cin >> A[i] >> B[i] >> C[i] >> D[i];
if (sw) swap(A[i], B[i]), swap(C[i], D[i]);
}
auto ans = solve(H, W, L, T, Q, A, B, C, D);
for (auto x : ans) cout << x << "\n";
}