// AC

#include <iostream>
#include <vector>

using namespace std;

const int N = 1010;
string g[N];
int s[N][N];

struct dat {
    int dl, dr, ul, ur;
    int c;
    
    dat() {}
    
    dat(int _l, int _r, int _c) : c(_c) {
        c = _c;
        dl = ul = _l;
        dr = ur = _r;
    }
    
    dat(int _dl, int _dr, int _ul, int _ur, int _c) :
        dl(_dl), dr(_dr), ul(_ul), ur(_ur), c(_c) {}
};

void flip(dat &a) {
    swap(a.dl, a.ul);
    swap(a.dr, a.ur);
}

dat merge(dat a, dat b) {
    int ml = max(a.ul, b.dl);
    int mr = min(a.ur, b.dr);
    int c = max(0, ml - mr);
    
    a.dl = min(a.dr, max(a.dl, ml));
    a.dr = max(a.dl, min(a.dr, mr));
    
    b.ul = min(b.ur, max(b.ul, ml));
    b.ur = max(b.ul, min(b.ur, mr));
    
    return dat(a.dl, a.dr, b.ul, b.ur, a.c + b.c + c);
}

int k;
vector<int> adj[N*N];
int jmp[20][N*N];
dat jdat[20][N*N];
int p[N*N], d[N*N];

void dfs(int u) {
    d[u] = d[p[u]] + 1;
    for (int v : adj[u]) {
        if (v != p[u]) {
            p[v] = u;
            dfs(v);
        }
    }
}

void init_tree(int n, vector<pair<int, int>> &e, vector<int> &l, vector<int> &r) {
    ++n;
    while ((1 << k) < 2*n) ++k;
    
    for (auto [u, v] : e) {
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    
    dfs(1);
    
    for (int i = 0; i < n; ++i) {
        jmp[0][i] = p[i];
        jdat[0][i] = dat(max(l[i], l[p[i]]), min(r[i], r[p[i]]), 1);
    }
    
    for (int j = 1; j < k; ++j) {
        for (int i = 0; i < n; ++i) {
            jmp[j][i] = jmp[j-1][jmp[j-1][i]];
            jdat[j][i] = merge(jdat[j-1][i], jdat[j-1][jmp[j-1][i]]);
        }
    }
}

dat dis(int u, int v) {
    if (u == v) return dat(0, N, 0);
    bool sw = 0;
    if (d[u] < d[v]) {
        swap(u, v);
        sw = 1;
    }
    
    dat udat, vdat;
    udat = vdat = dat(0, N, 0);
    
    for (int j = k-1; j >= 0; --j) {
        if (d[jmp[j][u]] >= d[v]) {
            udat = merge(udat, jdat[j][u]);
            u = jmp[j][u];
        }
    }
    
    if (u == v) {
        if (sw) flip(udat);
        return udat;
    }
    for (int j = k-1; j >= 0; --j) {
        if (jmp[j][u] != jmp[j][v]) {
            udat = merge(udat, jdat[j][u]);
            vdat = merge(vdat, jdat[j][v]);
            u = jmp[j][u];
            v = jmp[j][v];
        }
    }
    udat = merge(udat, jdat[0][u]);
    vdat = merge(vdat, jdat[0][v]);
    flip(vdat);
    udat = merge(udat, vdat);
    if (sw) flip(udat);
    return udat;
}

int main() {
    cin.tie(0) -> sync_with_stdio(0);
    
    int n, q;
    cin >> n >> q;
    
    for (int i = 0; i < n; ++i) {
        cin >> g[i];
    }
    
    vector<pair<int, int>> e;
    vector<int> l = {0}, r = {0};
    int w = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (g[i][j] == '#') {
                if (j == 0 || g[i][j-1] == '.') {
                    s[i][j] = ++w;
                    l.push_back(j);
                } else
                    s[i][j] = s[i][j-1];
                if (i > 0 && g[i-1][j] == '#' && (j == 0 || g[i][j-1] == '.' || g[i-1][j-1] == '.'))
                    e.push_back({s[i][j], s[i-1][j]});
                if (j == n-1 || g[i][j+1] == '.')
                    r.push_back(j);
            }
        }
    }
    
    init_tree(w, e, l, r);
    
    for (int i = 0; i < q; ++i) {
        int r1, c1, r2, c2;
        cin >> r1 >> c1 >> r2 >> c2;
        --r1;--c1;--r2;--c2;
        
        dat ans = dis(s[r1][c1], s[r2][c2]);
        if (ans.dl == ans.dr)
            cout << ans.c + abs(ans.dl - c1) + abs(ans.ul - c2) << '\n';
        else {
            int c3 = min(ans.dr, max(ans.dl, c1));
            cout << ans.c + abs(c3 - c1) + abs(c3 - c2) << '\n';
        }
    }
}
