#include <bits/stdc++.h>
#define NMAX 1000
using namespace std;
ifstream fi("pirati.in");
ofstream fo("pirati.out");
int n,m,q,cnta,cnti,x1,yy1,x2,yy2,le;
int mat[NMAX+5][NMAX+5],cod[NMAX+5][NMAX+5],viz[NMAX+5][NMAX+5];
vector<int> vecini[2*NMAX*NMAX+5];
vector<int> G[NMAX+5];
char ch;
int dx[]={-1,-1,-1,0,0,1,1,1};
int dy[]={-1,0,1,-1,1,-1,0,1};
int euler[2*NMAX*NMAX+5],L[2*NMAX*NMAX+5],ap[2*NMAX*NMAX+5];
int rmq[30][2*NMAX*NMAX+5],logg2[2*NMAX*NMAX+5];
void filll(int x,int y,int c){
cod[x][y]=c;
for(int i=0;i<8;i++){
x2=x+dx[i];
yy2=y+dy[i];
if(cod[x2][yy2]==0&&mat[x2][yy2]==mat[x][y]){
filll(x2,yy2,c);
}
}
}
int indice(int x){
if(x<0){
return 2*(-x);
}else{
return 2*x+1;
}
}
void cauta_vecini(int x,int y,int c){
viz[x][y]=1;
for(int i=0;i<8;i++){
x2=x+dx[i];
yy2=y+dy[i];
if(!viz[x2][yy2]){
if(cod[x2][yy2]==c){
cauta_vecini(x2,yy2,c);
}else if(cod[x2][yy2]!=-NMAX*NMAX-5){
vecini[indice(c)].push_back(indice(cod[x2][yy2]));
}
}
}
}
void remove_duplicates(vector<int> &v){
vector<int>::iterator it;
sort(v.begin(),v.end());
it=unique(v.begin(),v.end());
v.resize(distance(v.begin(),it));
}
void read(){
fi>>n>>m>>q;
n+=2;
m+=2;
for(int i=2;i<=n-1;i++){
for(int j=2;j<=m-1;j++){
fi>>ch;
mat[i][j]=ch-'0';
}
}
}
void get_tree(){
for(int i=0;i<=m+1;i++){
cod[0][i]=cod[n+1][i]=-NMAX*NMAX-5;
}
for(int i=0;i<=n+1;i++){
cod[i][0]=cod[i][m+1]=-NMAX*NMAX-5;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(!cod[i][j]){
if(!mat[i][j]){
++cnta;
filll(i,j,cnta);
}else{
++cnti;
filll(i,j,-cnti);
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(!viz[i][j]){
cauta_vecini(i,j,cod[i][j]);
}
}
}
int ind;
for(int i=1;i<=cnta;i++){
ind=indice(i);
remove_duplicates(vecini[ind]);
}
for(int i=1;i<=cnti;i++){
ind=indice(-i);
remove_duplicates(vecini[ind]);
}
for(int i=1;i<=cnta;i++){
ind=indice(i);
for(int j=0;j<vecini[ind].size();j++){
for(int jj=0;jj<vecini[vecini[ind][j]].size();jj++){
if(vecini[vecini[ind][j]][jj]!=ind){
G[i].push_back(vecini[vecini[ind][j]][jj]/2);
}
}
}
remove_duplicates(G[i]);
}
}
void dfs(int node, int level){
euler[++le]=node;
L[le]=level;
ap[node]=le;
for(int i=0;i<G[node].size();i++){
dfs(G[node][i],level+1);
euler[++le]=node;
L[le]=level;
}
}
void RMQ(){
rmq[0][1]=1;
for(int i=2;i<=le;i++){
logg2[i]=logg2[i>>2]+1;
rmq[0][i]=i;
}
for(int j=1;(1<<j)<=le;j++){
for(int i=1;i+(1<<j)-1<=le;i++){
if(L[rmq[j-1][i]]<=L[rmq[j-1][i+(1<<(j-1))]]){
rmq[j][i]=rmq[j-1][i];
}else{
rmq[j][i]=rmq[j-1][i+(1<<(j-1))];
}
}
}
}
int LCA(int n1,int n2){
if(ap[n1]>ap[n2]){
swap(n1,n2);
}
x1=ap[n1];
x2=ap[n2];
yy1=logg2[x2-x1+1];
if(L[rmq[yy1][x1]]<L[rmq[yy1][x2-(1<<yy1)+1]]){
return euler[rmq[yy1][x1]];
}
return euler[rmq[yy1][x2-(1<<yy1)+1]];
}
void solve(){
dfs(1,1);
RMQ();
int n1,n2,lca;
while(q--){
fi>>x1>>yy1>>x2>>yy2;
n1=cod[x1+1][yy1+1];
n2=cod[x2+1][yy2+1];
lca=LCA(n1,n2);
fo<<(L[ap[n1]]+L[ap[n2]]-2*L[ap[lca]])<<'\n';
}
}
int main(){
read();
get_tree();
solve();
fi.close();
fo.close();
}