#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = (1LL << 31) - 1;

struct segtree {
	int H, W, H_, W_;
	int dat[9000000];
	segtree() {}
	segtree(vector<vector<int>> &f) {
		init(f);
	}
	int x(int i, int j) {
		return i * W_ + j;
	}

	void init(vector<vector<int>> &f) {
		H = W = 1;
		while(H < (int)f.size()) H <<= 1;
		while(W < (int)f[0].size()) W <<= 1;
		H_ = 2 * H - 1, W_ = 2 * W - 1;
		for(int i = 0; i < (int)f.size(); i++)
			for(int j = 0; j < (int)f[0].size(); j++)
				dat[x(i + H - 1, j + W - 1)] = f[i][j];
		for(int i = 2 * H - 2; i > H - 2; i--)
			for(int j = W - 2; j >= 0; j--)
				dat[x(i, j)] = min(dat[x(i, 2 * j + 1)], dat[x(i, 2 * j + 2)]);
		for(int i = H - 2; i >= 0; i--)
			for(int j = 0; j < 2 * W - 1; j++)
				dat[x(i, j)] = min(dat[x(2 * i + 1, j)], dat[x(2 * i + 2, j)]);
	}
	int query(int li, int lj, int ri, int rj) { return query_h(li, lj, ri, rj, 0, H, 0); }
	int query_h(int li, int lj, int ri, int rj, int si, int ti, int k) {
		if(ri <= si || ti <= li) return INF;
		if(li <= si && ti <= ri) return query_w(lj, rj, 0, W, k, 0);
		const int mi = (si + ti) / 2;
		return min(query_h(li, lj, ri, rj, si, mi, 2 * k + 1), query_h(li, lj, ri, rj, mi, ti, 2 * k + 2));
	}
	int query_w(int lj, int rj, int sj, int tj, int i, int k) {
		if(rj <= sj || tj <= lj) return INF;
		if(lj <= sj && tj <= rj) return dat[x(i, k)];
		const int mj = (sj + tj) / 2;
		return min(query_w(lj, rj, sj, mj, i, 2 * k + 1), query_w(lj, rj, mj, tj, i, 2 * k + 2));
	}
};

vector<vector<int>> f;
segtree st;

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	int r, c, q;
	while(cin >> r >> c >> q, r | c | q) {
		f.assign(r, vector<int>(c, 0));
		for(int i = 0; i < r; i++) {
			for(int j = 0; j < c; j++) {
				cin >> f[i][j];
			}
		}

		st.init(f);
		while(q--) {
			int r1, c1, r2, c2;
			cin >> r1 >> c1 >> r2 >> c2;
			cout << st.query(r1, c1, r2 + 1, c2 + 1) << endl;
		}
	}
}