/**
 * Dont raise your voice, improve your argument.
 * --Desmond Tutu
 */
#include <bits/stdc++.h>
using namespace std;

const bool ready = [](){
    ios_base::sync_with_stdio(false); cin.tie(0);
    cout << fixed << setprecision(12);
    return true;
}();

using ld=long double;
const ld PI = acos((ld)-1);
using ll= long long;
#define int ll
#define all(v) (v).begin(), (v).end()
#define fori(n) for(int i=0; i<int(n); i++)

#define cini(i) int i; cin>>i;
#define cins(s) string s; cin>>s;
#define cind(d) ld d; cin>>d;
#define cinai(a,n) vi a(n); fori(n) { cin>>a[i]; }
#define cinas(s,n) vs s(n); fori(n) { cin>>s[i]; }
#define cinad(a,n) vd a(n); fori(n) { cin>>a[i]; }

using pii= pair<int, int>;
using pdd= pair<ld, ld>;
using vd= vector<ld>;
using vb= vector<bool>;
using vi= vector<int>;
using vvi= vector<vi>;
using vs= vector<string>;

#define endl "\n"

/*
 * dijkstra?
 * I mean, why not?
 * ->There are 500^2 vertex, so a lot of edges...
 *
 * Is it ever beneficial to go north?
 * -> Yes, can be :/
 *
 * Can we implement the North moves somewhat faster?
 * What about starting from the other end?
 * ...nothing
 *
 * Try dijkstra
 */
const int INF=1e18;
void solve() {
    cini(r);
    cini(c);

    vvi a(r, vi(c-1));
    for(int i=0; i<r; i++) 
        for(int j=0; j<c-1; j++)
            cin>>a[i][j];

    vvi b(r-1, vi(c));
    for(int i=0; i<r-1; i++) 
        for(int j=0; j<c; j++)
            cin>>b[i][j];

    vvi dp(r, vi(c, INF));
    dp[0][0]=0;
    using t3=tuple<int,int,int>;
    priority_queue<t3> q;   /* c, i, j */
    q.emplace(0, 0, 0);
    while(q.size()) {
        auto [cost,i,j]=q.top();
        if(i==r-1 && j==c-1) {
            cout<<dp[r-1][c-1]<<endl;
            return;
        }
        q.pop();
        if(-cost!=dp[i][j])
            continue;

        if(j+1<c && dp[i][j]+a[i][j]<dp[i][j+1]) {
            dp[i][j+1]=dp[i][j]+a[i][j];
            q.emplace(-dp[i][j+1], i, j+1);
        } 
        if(j>0 && dp[i][j-1]>dp[i][j]+a[i][j-1]) {
            dp[i][j-1]=dp[i][j]+a[i][j-1];
            q.emplace(-dp[i][j-1], i, j-1);
        }
        if(i+1<r && dp[i+1][j]>dp[i][j]+b[i][j]) {
            dp[i+1][j]=dp[i][j]+b[i][j];
            q.emplace(-dp[i+1][j], i+1, j);
        }
        for(int k=0; k<i; k++) {
            if(dp[k][j]>dp[i][j]+1+i-k) {
                dp[k][j]=dp[i][j]+1+i-k;
                q.emplace(-dp[k][j], k, j);
            }
        }
    }

    assert(false);
}

signed main() {
    solve();
}
#include <bits/stdc++.h>

#include <random>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#pragma GCC target("avx2")
#pragma GCC optimize("O3,unroll-loops")
using ll = long long;
using ull = unsigned long long;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define _overload3(_1, _2, _3, name, ...) name
#define _rep(i, n) for (int(i) = 0; (i) < int(n); (i)++)
#define repi(i, a, b) for (int(i) = (a); (i) < int(b); (i)++)
#define rep(...) _overload3(__VA_ARGS__, repi, _rep)(__VA_ARGS__)
template <class T>
bool chmax(T& a, const T& b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T>
bool chmin(T& a, const T& b) {
    if (b < a) {
        a = b;
        return 1;
    }
    return 0;
}
constexpr int dy[4] = {-1, 0, 1, 0};
constexpr int dx[4] = {0, -1, 0, 1};
constexpr ll MOD = 1'000'000'007LL; /*998'244'353LL;*/

template <typename T>
struct Dijkstra {
    vector<vector<pair<int, short>>> e;
    vector<T> cost;
    Dijkstra(int V) : e(V) {}
    void add(int u, int v, T weight) {
        e[u].push_back({v, weight});
        e[v].push_back({u, weight});
    }
    void add_directed(int from, int to, T weight) {
        e[from].push_back({to, weight});
    }
    vector<T>& calculate(int s, T def) {
        cost.resize(e.size(), def);
        priority_queue<pair<T, int>> pq;
        cost[s] = 0;
        pq.push({0, s});
        while (!pq.empty()) {
            int n = pq.top().second;
            if (-pq.top().first != cost[n]) {
                pq.pop();
                continue;
            }
            pq.pop();
            for (int i = 0; i < e[n].size(); i++) {
                if (cost[e[n][i].first] > cost[n] + e[n][i].second) {
                    cost[e[n][i].first] = cost[n] + e[n][i].second;
                    pq.push({-cost[e[n][i].first], e[n][i].first});
                }
            }
        }
        return cost;
    }
};

int R, C;
Dijkstra<int> G(0);

signed main() {
    cin >> R >> C;
    G = Dijkstra<int>(2 * R * C);
    rep(i, R) {
        rep(j, C - 1) {
            int a;
            cin >> a;
            G.add(i * C + j, i * C + j + 1, a);
        }
    }
    rep(i, R - 1) {
        rep(j, C) {
            int a;
            cin >> a;
            G.add_directed(i * C + j, (i + 1) * C + j, a);
        }
    }
    rep(i, R) {
        rep(j, C) {
            G.add_directed(i * C + j, R * C + i * C + j, 1);
            G.add_directed(R * C + i * C + j, i * C + j, 0);
            if (i - 1 >= 0)
                G.add_directed(R * C + i * C + j, R * C + (i - 1) * C + j, 1);
        }
    }
    cout << G.calculate(0, 2e9)[R * C - 1] << endl;
}