#include <bits/stdc++.h>

#define endl '\n'
#define TRACE(x) cerr << #x << " = " << x << endl

using namespace std;
template<class T, class T1> inline bool chkmax(T &x, const T1 &y) { return x < y ? x = y, true : false; }
template<class T, class T1> inline bool chkmin(T &x, const T1 &y) { return x > y ? x = y, true : false; }

const int MAXN = 1002;

int n, m;

void read() {
    cin >> n >> m;
}

int tree[MAXN][MAXN];

void update(int x, int y, int delta) {
    for (int i = x; i <= n; i += (i & (-i))) {
        for (int j = y; j <= m; j += (j & (-j))) tree[i][j] += delta;
    }
}

int query(int x, int y) {
    int ans = 0;
    for (int i = x; i; i -= (i & (-i))) {
        for (int j = y; j; j -= (j & (-j))) ans += tree[i][j];
    }
    return ans;
}

int query(int x1, int y1, int x2, int y2) {
    return query(x2, y2) - query(x2, y1 - 1) - query(x1 - 1, y2) + query(x1 - 1, y1 - 1);
}

bool ok(int len) {
    for (int i = 1; i <= n - len + 1; i++) {
        for (int j = 1; j <= m - len + 1; j++) {
            if (!query(i, j, i + len - 1, j + len - 1)) return true;
        }
    }
    return false;
}

void solve() {
    memset(tree, 0, sizeof(tree));
    int q;
    cin >> q;
    for (int i = 0; i < q; i++) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        for (int j = x1; j <= x2; j++) {
            for (int k = y1; k <= y2; k++) update(j, k, 1);
        }
    }
    int low = 1, high = min(n, m);
    int ans = 0;
    while (low <= high) {
        int mid = (low + high) >> 1;
        if (ok(mid)) {
            ans = mid;
            low = mid + 1;
        } else high = mid - 1;
    }
    cout << ans << endl;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    read();
    solve();

    return EXIT_SUCCESS;
}
