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

#include <cstring>

#include <algorithm>

#include <iostream>



using namespace std;

typedef long long LL;

const int oo = 0x7fffffff;

const int Max = 1048576;

const int MaxN = 15;

const int MaxLg = 16;

int A[Max],Log[MaxN+1],tableMin[MaxN][MaxLg];

void makeRMinQ(int *a,int s,int t){

	int i,j,n = t-s;

	for (i = s;i < t;i++) tableMin[i-s][0] = a[i];

	//for (i = s;i < t;i++)printf("%d ",a[i]);puts("");

	for (j = 1;(1 << j) <= n;j++)

		for (i = s;i+(1 << j) <= t;i++)

			tableMin[i-s][j] = min(tableMin[i-s][j-1],tableMin[i-s+(1 << (j-1))][j-1]);

}

int QueryMin(int x,int y){

	int p = Log[y-x+1];//calLog2(y-x+1);

    //printf("%d %d=> %d %d\n",x,y,y-x+1,p);

	return min(tableMin[x][p],tableMin[y-(1 << p)+1][p]);

}

const int MaxQ = 10010;

struct query{

    int x1,y1,x2,y2;

};

query fQ[MaxQ];

int Res[MaxQ];

int main(){

	for (int i = 0,x = 0,cd = 2;i <= MaxN;x++,cd<<=1)

		while (i <= MaxN && i < cd)

		    Log[i++] = x;

    for (int R,C,Q;scanf("%d%d%d",&R,&C,&Q) && R;){

        if (R <= C){

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

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

                    scanf("%d",&A[i*C+j]);

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

                scanf("%d%d%d%d",&fQ[q].x1,&fQ[q].y1,&fQ[q].x2,&fQ[q].y2);

        }else{

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

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

                    scanf("%d",&A[j*R+i]);

            swap(R,C);

            for (int q = 0;q < Q;q++){

                scanf("%d%d%d%d",&fQ[q].x1,&fQ[q].y1,&fQ[q].x2,&fQ[q].y2);

                swap(fQ[q].x1,fQ[q].y1);

                swap(fQ[q].x2,fQ[q].y2);

            }

        }

//        for (int i = 0;i < R;i++)

//            for (int j = 0;j < C;j++)

//                A[i*C+j] = rand();

//        for (int q = 0;q < Q;q++){

//            int x1 = rand() % R;

//            int x2 = rand() % R;

//            int y1 = rand() % C;

//            int y2 = rand() % C;

//            if (x1 > x2) swap(x1,x2);

//            if (y1 > y2) swap(y1,y2);

//            fQ[q].x1 = x1;

//            fQ[q].y1 = y1;

//            fQ[q].x2 = x2;

//            fQ[q].y2 = y2;

//        }

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

            Res[q] = oo;

        //for (int q = 0;q < Q;q++)printf("(%d,%d)-(%d,%d)\n",fQ[q].x1,fQ[q].y1,fQ[q].x2,fQ[q].y2);

        int fC = (C-1) / MaxN+1;

        for (int i = 0;i < R;i++){

            for (int j = 0,k = 0;j < fC;j++){

                int nk = min(C,k+MaxN);

                //printf("add %d [%d,%d): ",i,k,nk);

                makeRMinQ(A,i*C+k,i*C+nk);

                for (int q = 0;q < Q;q++){

                    if (i < fQ[q].x1 || fQ[q].x2 < i)

                        continue;

                    int cs = max(fQ[q].y1,k);

                    int ct = min(fQ[q].y2,nk-1);

                    if (cs > ct) continue;

                    //printf("%d : (%d,%d) %d\n",q,cs,ct,QueryMin(cs-k,ct-k));

                    Res[q] = min(Res[q],QueryMin(cs-k,ct-k));

                }

                k = nk;

            }

        }

//        for (int q = 0;q < Q;q++){

//            int x1 = fQ[q].x1;

//            int y1 = fQ[q].y1;

//            int x2 = fQ[q].x2;

//            int y2 = fQ[q].y2;

//            int cr = oo;

//            for (int i = x1;i <= x2;i++)

//                for (int j = y1;j <= y2;j++)

//                    cr = min(cr,A[i*C+j]);

//            if (cr != Res[q]){

//                printf("Fail!!\n");

////                for (int i = 0;i < R;i++){

////                    for (int j = 0;j < C;j++)

////                        printf("%d ",A[i*C+j]);

////                    puts("");

////                }

//                printf("%d %d %d %d\n",x1,y1,x2,y2);

//                printf("=> %d %d\n",cr,Res[q]);

//                while (1);

//            }

//        }

//        puts("ok");

//        for (int i = 0;i < R;i++){

//            for (int j = 0;j < C;j++)

//                printf("%d ",A[i*C+j]);

//            puts("");

//        }

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

            printf("%d\n",Res[q]);

    }

    return 0;

}

// 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: