#pragma GCC optimize("O2")
#pragma GCC target("avx")
#pragma clang optimize on
#include <cstdio>
#include <functional>
#include <queue>
#include <tuple>
using namespace std;

inline int_fast32_t get_digit() {
    int_fast32_t x = 0, f = 1;
    char c = getchar();
    while(c > '9' || c < '0') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x * 10) + (c ^ 48);
        c = getchar();
    }
    return x * f;
}

int main() {
    int_fast32_t R, C;
    scanf("%d%d", &R, &C);
    int_fast32_t A[250000], B[250000];
    int_fast32_t dist[500000], seen[500000] = {0}, cost, pt, to_hide = R * C;
    priority_queue<pair<int_fast32_t, int_fast32_t>, vector<pair<int_fast32_t, int_fast32_t>>,
                   greater<pair<int_fast32_t, int_fast32_t>>>
        queue;
    for(int_fast32_t i = 0; i < R * C; ++i)
        if(i % C != C - 1) A[i] = get_digit();
    for(int_fast32_t i = 0; i < (R - 1) * C; ++i) B[i] = get_digit();
    for(int_fast32_t i = 1; i < to_hide + to_hide; ++i) dist[i] = 10000000;
    queue.emplace(pair<int_fast32_t, int_fast32_t>(0, 0));
    while(!queue.empty()) {
        tie(cost, pt) = queue.top();
        if(pt == to_hide - 1) break;
        queue.pop();
        seen[pt] = true;
        if(pt < to_hide) {
            if(!seen[pt + 1] && pt % C != C - 1) {
                if(cost + A[pt] < dist[pt + 1]) {
                    dist[pt + 1] = cost + A[pt];
                    queue.emplace(pair<int_fast32_t, int_fast32_t>(dist[pt + 1], pt + 1));
                }
            }
            if(!seen[pt - 1] && pt % C != 0) {
                if(cost + A[pt - 1] < dist[pt - 1]) {
                    dist[pt - 1] = cost + A[pt - 1];
                    queue.emplace(pair<int_fast32_t, int_fast32_t>(dist[pt - 1], pt - 1));
                }
            }
            if(!seen[pt + C] && pt < to_hide - C) {
                if(cost + B[pt] < dist[pt + C]) {
                    dist[pt + C] = cost + B[pt];
                    queue.emplace(pair<int_fast32_t, int_fast32_t>(dist[pt + C], pt + C));
                }
            }
            if(!seen[pt + to_hide] && cost + 1 < dist[pt + to_hide]) {
                dist[pt + to_hide] = cost + 1;
                queue.emplace(pair<int_fast32_t, int_fast32_t>(dist[pt + to_hide], pt + to_hide));
            }
        } else {
            if(to_hide < pt - C && !seen[pt - C] && cost + 1 < dist[pt - C]) {
                dist[pt - C] = cost + 1;
                queue.emplace(pair<int_fast32_t, int_fast32_t>(cost + 1, pt - C));
            }
            if(!seen[pt - to_hide] && cost < dist[pt - to_hide]) {
                dist[pt - to_hide] = cost;
                queue.emplace(pair<int_fast32_t, int_fast32_t>(cost, pt - to_hide));
            }
        }
    }
    printf("%d\n", dist[to_hide - 1]);
}
#include "bits/stdc++.h"
using namespace std;

#define fi first
#define se second
#define pb push_back
#define int long long
#define all(x) (x).begin(), (x).end()

using LL = long long;
using LD = long double;
using pii = pair<int, int>;
using tiii = tuple<int, int, int>;
using vii = vector<pii>;
using viii = vector<tiii>;

const int INF = 1e18;
const int MOD = 1e9 + 7;
const int N = 505;

int R, C;
int A[N][N];
int B[N][N];
viii g[N + N][N + N];

int32_t main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);

    cin >> R >> C;

    for (int r = 1; r <= R; r++) {
        for (int c = 1; c <= C - 1; c++) {
            cin >> A[r][c];
        }
    }

    for (int r = 1; r <= R - 1; r++) {
        for (int c = 1; c <= C; c++) {
            cin >> B[r][c];
        }
    }

    for (int r = 1; r <= R; r++) {
        for (int c = 1; c <= C; c++) {
            if (c + 1 <= C)
                g[r][c].pb({r, c + 1, A[r][c]});
            
            if (c - 1 >= 1)
                g[r][c].pb({r, c - 1, A[r][c - 1]});
            
            if (r + 1 <= R)
                g[r][c].pb({r + 1, c, B[r][c]});
            
            g[r][c].pb({r + R, c + C, 1});
            g[r + R][c + C].pb({r, c, 0});
            if (r - 1 >= 1) {
                g[r + R][c + C].pb({r - 1 + R, c + C, 1});
            }
        }
    }

    auto dijkstra = [&] (int x0, int y0) {
        vector<vector<int>> dist(2*R + 1, vector<int>(2*C + 1, INF));
        dist[x0][y0] = 0;
        
        set<tiii> S;
        S.insert({0, x0, y0});

        while (!S.empty()) {
            auto [d, x1, y1] = *S.begin();
            S.erase(S.begin());

            for (auto [x2, y2, z]: g[x1][y1]) {
                if (dist[x2][y2] > d + z) {
                    S.erase({dist[x2][y2], x2, y2});
                    dist[x2][y2] = d + z;
                    S.insert({dist[x2][y2], x2, y2});
                }
            }
        }

        return dist[R][C];
    };

    cout << dijkstra(1, 1) << "\n";
}