#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
#define DEBUG(...) debug(#__VA_ARGS__, __VA_ARGS__)
#else
#define DEBUG(...) 6
#endif

template<typename T, typename S> ostream& operator << (ostream &os, const pair<T, S> &p) {return os << "(" << p.first << ", " << p.second << ")";}
template<typename C, typename T = decay<decltype(*begin(declval<C>()))>, typename enable_if<!is_same<C, string>::value>::type* = nullptr>
ostream& operator << (ostream &os, const C &c) {bool f = true; os << "["; for (const auto &x : c) {if (!f) os << ", "; f = false; os << x;} return os << "]";}
template<typename T> void debug(string s, T x) {cerr << s << " = " << x << "\n";}
template <typename T, typename... Args> void debug(string s, T x, Args... args) {for (int i=0, b=0; i<(int)s.size(); i++) if (s[i] == '(' || s[i] == '{') b++; else
if (s[i] == ')' || s[i] == '}') b--; else if (s[i] == ',' && b == 0) {cerr << s.substr(0, i) << " = " << x << " | "; debug(s.substr(s.find_first_not_of(' ', i + 1)), args...); break;}}

typedef tuple<int, int, int, int> node;

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

    int n, m;
    cin >> n >> m;
    vector<vector<int>> a(n, vector<int>(m-1)), b(n-1, vector<int>(m));
    for (int i=0; i<n; i++)
        for (int j=0; j<m-1; j++)
            cin >> a[i][j];
    for (int i=0; i<n-1; i++)
        for (int j=0; j<m; j++)
            cin >> b[i][j];

    vector<vector<vector<int>>> dist(n, vector<vector<int>>(m, vector<int>(2, 1e9)));
    priority_queue<node, vector<node>, greater<node>> pq;

    auto relax = [&] (int d, int r, int c, int f) -> void {
        if (d < dist[r][c][f])
            pq.emplace(dist[r][c][f] = d, r, c, f);
    };

    relax(0, 0, 0, 0);
    while (!pq.empty()) {
        auto [d, r, c, f] = pq.top();
        pq.pop();
        if (d > dist[r][c][f])
            continue;
        if (f) {
            relax(d, r, c, 0);
            if (r > 0) relax(d + 1, r - 1, c, f);
        } else {
            if (r > 0) relax(d + 2, r - 1, c, 1);
            if (r + 1 < n) relax(d + b[r][c], r + 1, c, f);
            if (c > 0) relax(d + a[r][c-1], r, c - 1, f);
            if (c + 1 < m) relax(d + a[r][c], r, c + 1, f);
        }
    }
    cout << dist[n-1][m-1][0] << "\n";

    return 0;
}

/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author tatsumack
 */

#include <iostream>
#include <fstream>

#include <bits/stdc++.h>

#define int long long
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define FOR(i, a, b) for (int i = (a), i##_len = (b); i <= i##_len; ++i)
#define REV(i, a, b) for (int i = (a); i >= (b); --i)
#define CLR(a, b) memset((a), (b), sizeof(a))
#define DUMP(x) cout << #x << " = " << (x) << endl;
#define INF 1001001001001001001ll
#define fcout cout << fixed << setprecision(12)

using namespace std;
typedef pair<int, int> P;

class E {
public:
    void solve(std::istream& cin, std::ostream& cout) {
        int R, C;
        cin >> R >> C;
        vector<vector<int>> A(R, vector<int>(C - 1));
        vector<vector<int>> B(R - 1, vector<int>(C));
        REP(i, R) REP(j, C - 1) cin >> A[i][j];
        REP(i, R - 1) REP(j, C) cin >> B[i][j];

        vector<int> dist(R * C * 2, INF);
        dist[0] = 0;
        priority_queue<P, vector<P>, greater<>> pq;
        pq.push({0, 0});
        while (!pq.empty()) {
            int cost, v;
            tie(cost, v) = pq.top();
            pq.pop();
            //cout << v << ":" << cost << endl;
            int x = v % R;
            int y = v / R;
            if (v >= R * C) {
                if (x - 1 >= 0) {
                    int nv = R * y + x - 1;
                    if (cost + 1 < dist[nv]) {
                        dist[nv] = cost;
                        pq.push({cost + 1, nv});
                    }
                }
                int nv = v - R * C;
                if (cost < dist[nv]) {
                    dist[nv] = cost;
                    pq.push({cost, nv});
                }
            } else {
                int nv = v + R * C;
                if (cost + 1 < dist[nv]) {
                    dist[nv] = cost + 1;
                    pq.push({cost + 1, nv});
                }
                if (y + 1 <= C - 1) {
                    nv = R * (y + 1) + x;
                    if (cost + A[x][y] < dist[nv]) {
                        dist[nv] = cost + A[x][y];
                        pq.push({cost + A[x][y], nv});
                    }
                }
                if (y - 1 >= 0) {
                    nv = R * (y - 1) + x;
                    if (cost + A[x][y - 1] < dist[nv]) {
                        dist[nv] = cost + A[x][y - 1];
                        pq.push({cost + A[x][y - 1], nv});
                    }
                }
                if (x + 1 <= R - 1) {
                    nv = R * y + x + 1;
                    if (cost + B[x][y] < dist[nv]) {
                        dist[nv] = cost + B[x][y];
                        pq.push({cost + B[x][y], nv});
                    }
                }
            }
        }
        cout << dist[R * C - 1] << endl;
    }
};


signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    std::istream& in(std::cin);
    std::ostream& out(std::cout);

    E solver;
    solver.solve(in, out);
    return 0;
}
