#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define int ll

#define REP(i,n) for(int i=0;i<n;++i)
#define ALL(name) name.begin(),name.end()
#define SORT(name) sort(name.begin(), name.end())
#define ZERO(p) memset(p, 0, sizeof(p))
#define MINUS(p) memset(p, -1, sizeof(p))
#if 0
#  define DBG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#  define DBG(fmt, ...)
#endif

const ll LLINF = (1LL<<60);
const int INF = (1LL<<30);
const double DINF = std::numeric_limits<double>::infinity();
const int MOD = 1000000007;
#define MAX_N 8000
#define SUBMIT

int H, W;
vector< vector<int> > A, B, AB;
int dp[81][81][MAX_N];

// 今 [i][j] にいて、現在の偏りが n のときの最小の偏り
int dfs(int i, int j, int n) {
    DBG("i: %lld j: %lld n: %lld\n", i, j, n);
    if(i == H-1 && j == W-1) {
        int cand1 = n + AB[i][j];
        int cand2 = abs(n - AB[i][j]);
        dp[i][j][n] = min(cand1, cand2);
        DBG("%lld, %lld\n", cand1, cand2);
        return dp[i][j][n];
    }

    // 考慮しない
    if(n >= MAX_N) { return LLINF; }

    int& ret = dp[i][j][n];
    if(~ret) { return ret; }
    ret = LLINF;

    // n に対して足すパターン
    int n1 = abs(n + AB[i][j]);
    if(j < W-1) { ret = min(ret, dfs(i, j + 1, n1)); }
    if(i < H-1) { ret = min(ret, dfs(i + 1, j, n1)); }

    // n に対して引くパターン
    int n2 = abs(n - AB[i][j]);
    if(j < W-1) { ret = min(ret, dfs(i, j + 1, n2)); }
    if(i < H-1) { ret = min(ret, dfs(i + 1, j, n2)); }

    return ret;
}

int solve() {
    MINUS(dp);
    return dfs(0, 0, 0);
}

int b_ans = LLINF;
int b_dfs(int i, int j, int r, int b) {
    if(i == H-1 && j == W-1) {
        b_ans = min({b_ans, abs((r + A[i][j]) - (b + B[i][j])), abs((r + B[i][j]) - (b + A[i][j])) });
        return 0;
    }

    if(j < W-1) {
        b_dfs(i, j + 1, r + A[i][j], b + B[i][j]);
        b_dfs(i, j + 1, r + B[i][j], b + A[i][j]);
    }
    if(i < H-1) {
        b_dfs(i + 1, j, r + A[i][j], b + B[i][j]);
        b_dfs(i + 1, j, r + B[i][j], b + A[i][j]);
    }

    return 0;
}
int brute_force() {
    b_dfs(0, 0, 0, 0);
    return b_ans;
}

signed main() {
    cin.tie(0); cout.tie(0);
    ios::sync_with_stdio(false);
#ifdef SUBMIT

    cin >> H >> W;

    A.assign(H, vector<int>(W, 0));
    B.assign(H, vector<int>(W, 0));
    AB.assign(H, vector<int>(W, 0));
    REP(i, H) {
        REP(j, W) {
            cin >> A[i][j];
        }
    }
    REP(i, H) {
        REP(j, W) {
            cin >> B[i][j];
            AB[i][j] = abs(A[i][j] - B[i][j]);
        }
    }

    int ans = solve();
    printf("%lld\n", ans);
#else
    random_device r;
    mt19937 mt(r());
    uniform_int_distribution<> dist(0, 9);

    H = 2;
    W = 2;
    REP(loop, 100) {
        A.assign(H, vector<int>(W, 0));
        B.assign(H, vector<int>(W, 0));
        AB.assign(H, vector<int>(W, 0));
        REP(i, H) {
            REP(j, W) {
                A[i][j] = dist(mt);
                B[i][j] = dist(mt);
                AB[i][j] = abs(A[i][j] - B[i][j]);
            }
        }

        int cand = solve();
        int ans = brute_force();
        if(cand != ans) {
            printf("A:\n");
            REP(i, H) {
                REP(j, W) {
                    printf("%lld ", A[i][j]);
                }
                printf("\n");
            }
            printf("B:\n");
            REP(i, H) {
                REP(j, W) {
                    printf("%lld ", B[i][j]);
                }
                printf("\n");
            }
            printf("AB:\n");
            REP(i, H) {
                REP(j, W) {
                    printf("%lld ", AB[i][j]);
                }
                printf("\n");
            }
            printf("cand: %lld\n", cand);
            printf("ans:  %lld\n", ans);
            return 0;
        }
    }

#endif

    return 0;
}


Measured memory_bytes: 410496