// Original C++ solution (slower):
#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <cstdlib>

#include <algorithm>

#include <vector>

#include <set>

using namespace std;

const int maxn=1500032;



int mm[maxn*4];

int aa[maxn];

int S, inf, L, r1, c1, r2, c2;

void init(int s, int x, int l, int r)

{

	if (s==0) if (s+x>S) S=s+x;

	if (l==r) { mm[s+x]=aa[l]; //printf("ll %d %d \n", l, aa[l]); 

	return ; }

    int m=(l+r)>>1;

	init(s, x*2, l, m); init(s, x*2+1, m+1, r);

	mm[s+x]=min(mm[s+x*2], mm[s+x*2+1]);

    //printf("nb %d %d\n", s+x, mm[s+x]);

}



int query(int s, int x, int l, int r, int L, int R)

{

	if (L<=l && r<=R) return  mm[s+x];

	int m=(l+r)>>1;

	int ans=inf;

	if (L<=m) ans=min(ans, query(s, 2*x, l, m, L, R));

	if (R>=m+1) ans=min(ans, query(s, 2*x+1, m+1, r, L, R)); 

    return ans;

}



int r, c, q;

int main() 

{

    while (scanf("%d %d %d", &r, &c, &q)!=-1)

	{

		if (r==0 && c==0 && q==0) break;

	    for (int i=0; i<r; i++) 

			for (int j=0; j<c; j++)

		if (r<=c) scanf("%d", &aa[i*c+j+1]); else scanf("%d", &aa[j*r+i+1]); 

		//puts("aa");

        inf=0;

		for (int i=1; i<=r*c; i++) 

		{

			inf=max(inf, aa[i]);

		    //printf("list %d %d\n", i, aa[i]);

		}

		if (r<=c)

		{

			S=0;

			L=c;

			init(0, 1, 1, c);

			//printf("%d %d\n", mm[1], S);

            for (int i=2; i<=r; i++)

			{

				init(S*(i-1), 1, 1+(i-1)*L, i*L);

		        //printf("%d\n", mm[S*(i-1)+1]);

            }

		} else

		{

			S=0;

			L=r;

			init(0, 1, 1, r);

			for (int i=2; i<=c; i++)

			{

				init(S*(i-1), 1, 1+(i-1)*L, i*L);

			}

		}

        //puts("bb");

	    while (q--)

		{

			scanf("%d %d %d %d", &r1, &c1, &r2, &c2);

            r1++; r2++; c1++; c2++;

			//printf("%d %d %d %d\n", r1, c1, r2, c2);

			int ans=inf;

			if (r<=c)

			{

				for (int i=r1; i<=r2; i++)

				{

					ans=min(ans, query(S*(i-1), 1, 1+(i-1)*L, i*L, c1+(i-1)*L, c2+(i-1)*L));  

				//    printf("%d\n", ans);

				}

				printf("%d\n", ans);

			} else

			{

				for (int i=c1; i<=c2; i++)

				{

					//for (int j=r1+(i-1)*L; j<=r2+(i-1)*L; j++)

					//	printf("%d %d\n", j, aa[j]); 

					ans=min(ans, query(S*(i-1), 1, 1+(i-1)*L, i*L, r1+(i-1)*L, r2+(i-1)*L));  

				    //printf("eee %d\n", query(S*(i-1), 1, 1+(i-1)*L, i*L, r1+(i-1)*L, r2+(i-1)*L));  

				    //printf("%d\n", ans);

				}

				printf("%d\n", ans);

			}

		}

	}

	return 0;

}

/*

4 2 10

1 2

2 1

0 7

1 2

1 0 2 1

*/

// Optimized solution to the same problem (faster):
#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <algorithm>



using namespace std;



const int maxn=1e6+5;



int tree[16*maxn],n,m,f[maxn],q;

int r1,r2,c1,c2;



void ini0(int pos1,int pos2,int begin,int end,int r)

{

    if(begin==end)tree[pos1*m*4+pos2]=f[r*m+begin];

    else

    {

        int mid=(begin+end)>>1;

        ini0(pos1,pos2<<1,begin,mid,r);

        ini0(pos1,(pos2<<1)|1,mid+1,end,r);

        if(tree[pos1*m*4+(pos2<<1)]<tree[pos1*m*4+((pos2<<1)|1)])tree[pos1*m*4+pos2]=tree[pos1*m*4+(pos2<<1)];

        else tree[pos1*m*4+pos2]=tree[pos1*m*4+((pos2<<1)|1)];

    }

}



void ini1(int pos1,int pos2,int begin,int end)

{

    if(tree[(pos1<<1)*m*4+pos2]<tree[((pos1<<1)|1)*m*4+pos2])tree[pos1*m*4+pos2]=tree[(pos1<<1)*m*4+pos2];

    else tree[pos1*m*4+pos2]=tree[((pos1<<1)|1)*m*4+pos2];

    if(begin!=end)

    {

        int mid=(begin+end)>>1;

        ini1(pos1,pos2<<1,begin,mid);

        ini1(pos1,(pos2<<1)|1,mid+1,end);

    }

}



void ini(int pos,int begin,int end)

{

    if(begin==end)ini0(pos,1,0,m-1,begin);

    else

    {

        int mid=(begin+end)>>1;

        ini(pos<<1,begin,mid);

        ini((pos<<1)|1,mid+1,end);

        ini1(pos,1,0,m-1);

    }

}



int find2(int pos1,int pos2,int begin,int end)

{

    if(c1<=begin && end<=c2)return tree[pos1*4*m+pos2];

    else

    {

        int mid=(begin+end)>>1;

        if(c2<=mid)return find2(pos1,pos2<<1,begin,mid);

        else if(c1>mid)return find2(pos1,(pos2<<1)|1,mid+1,end);

        else return min(find2(pos1,pos2<<1,begin,mid),find2(pos1,(pos2<<1)|1,mid+1,end));

    }

}



int find(int pos,int begin,int end)

{

    if(r1<=begin && end<=r2)return find2(pos,1,0,m-1);

    else

    {

        int mid=(begin+end)>>1;

        if(r2<=mid)return find(pos<<1,begin,mid);

        else if(r1>mid)return find((pos<<1)|1,mid+1,end);

        else return min(find(pos<<1,begin,mid),find((pos<<1)|1,mid+1,end));

    }

}



int main()

{

    while(scanf("%d%d%d",&n,&m,&q)==3 && (n||m||q))

    {

        for(int i=0;i<n;i++)

            for(int j=0;j<m;j++)

                scanf("%d",&f[i*m+j]);

        ini(1,0,n-1);

        for(int i=0;i<q;i++)

        {

            scanf("%d%d%d%d",&r1,&c1,&r2,&c2);

            printf("%d\n",find(1,0,n-1));

        }

    }

    return 0;

}

// Fastest known solution for this problem: