#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(ll i=0,endrep=(n); i<endrep; ++i)
#define rep1(i,n) for(ll i=1,endrep=(n); i<=endrep; ++i)
#define revrep(i,n) for(ll i=(ll)(n)-1; i>=0; --i)
inline constexpr ll Inf = (1ULL << 60) -123456789;
#define fastio cin.tie(0); ios_base::sync_with_stdio(false); cout<<fixed<<setprecision(10);
#define newl '\n'
#define YN(e) ((e)?"Yes":"No")
#define all(a) begin(a),end(a)
#define rall(a) rbegin(a),rend(a)
#define delif(c,pred) (c).erase(remove_if(all(c),(pred)), end(c))
template <class T,class U> bool updmax(T& a, U b) { if(b>a){ a=b; return true;} return false;}
template <class T,class U> bool updmin(T& a, U b) { if(b<a){ a=b; return true;} return false;}
inline constexpr int Mod = 1000000007;
//inline constexpr int Mod = 998244353;
#define dbg(a) cerr << #a << ": " << a << endl;
#define dbgs(s) cerr << #s << endl;
#define dbg1(a,n) cerr<<#a<<": "; rep(i,n) cerr<<a[i]<<" "; cerr<<endl;
#define dbg2(m,h,w) cerr<<#m<<":"<<endl; rep(i,h){ rep(j,w)cerr<<m[i][j]<<" "; cerr<<endl; }
template <class T, class U> ostream& operator << (ostream& os, pair<T,U> v) {os<<v.first<<","<<v.second;return os;}
template <class T, size_t N> ostream& operator << (ostream& os, array<T,N> v) {rep(i,N)os<<v[i]<<(i+1<(ll)N?" ":"");return os;}
int rng(int n) { return rand()/(RAND_MAX+1.0)*n; }

using P = pair<ll,ll>;
ll a[505][505], b[505][505];
int main() {
    fastio;
    ll r,c;
    cin >> r >> c;
    auto z = [&](ll v, ll h, ll f=0)->ll { return f*r*c + v*c + h; };
    auto rz = [&](ll p)->array<ll,3> { return {p%(r*c)/c, p%c, p/(r*c)}; };
    rep(i,r) rep(j,c-1) cin >> a[i][j];
    rep(i,r-1) rep(j,c) cin >> b[i][j];
    priority_queue<P,vector<P>, greater<>> q;
    vector<ll> cost(r*c*2, Inf);
    q.push({0,z(0,0)});
    cost[z(0,0)] = 0;
    while (!q.empty()) {
        auto [co,p] = q.top(); q.pop();
        auto [v,h,f] = rz(p);
        if (co != cost[p]) continue;
        auto push = [&, co=co](ll nc, ll np) { if (updmin(cost[np], co+nc)) q.push({co+nc,np}); };
        if (f == 0) {
            if (h < c-1) push(a[v][h], z(v,h+1,0));
            if (h > 0) push(a[v][h-1], z(v,h-1,0));
            if (v < r-1) push(b[v][h], z(v+1,h,0));
            if (v > 0) push(1, z(v,h,1));
        } else {
            if (v < r-1) push(0, z(v,h,0));
            if (v > 0) push(1, z(v-1,h,1));
        }
    }
    ll ans = cost[z(r-1,c-1,0)];
    cout << ans << endl;
}

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define all(x) (x).begin(), (x).end()
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vector<bool>> vvb;
typedef vector<vector<int>> vvi;
typedef vector<vector<ll>> vvl;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void debugF(ostream &os) {os << endl;}
template <typename Head, typename... Tail>
void debugF(ostream &os, Head H, Tail... T) { os << " " << H; debugF(os, T...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debugF(cerr, __VA_ARGS__)
template<typename T> istream &operator>>(istream &is, vector<T> &v){ for (auto &x : v) is >> x; return is; }
template<typename T> ostream &operator<<(ostream &os, vector<T> &v){ for(int i = 0; i < v.size(); os << (i>0 ? " ":"") << v[i++]); return os;}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

class Dijkstra{
public:
    static vl solve(vector<vector<pii>> &g, int s, int target = -1){
        //g[v] = list of (u,w) , where v->u with weight w.
        int n = g.size();
        assert(s >= 0 && s < n);

        vl dist(n, -1);
        vector<bool> used(n, false);
        set<pair<ll,int>> S;
        S.insert({0,s});
        
        while(!S.empty()){
            auto min_data = *S.begin();
            S.erase(S.begin());

            ll min_dist = min_data.first;
            int v = min_data.second;
            dist[v] = min_dist;
            used[v] = true;

            if(target == v)
                break;

            for(auto u_data : g[v]){
                int u = u_data.first;
                int w = u_data.second;
                if(w < 0){
                    throw new invalid_argument("graph with negative edges");
                }
                if(used[u])
                    continue;                    
                if(dist[u] == -1 || (dist[v]+w < dist[u])){
                    if(dist[u] != -1)
                        S.erase({dist[u],u});
                    dist[u] = dist[v] + w;
                    S.insert({dist[u],u});
                }
            }
        }
        return dist;
    }
};

void solve(){
    int n, m, i, j, u, v;
    cin >> n >> m;

    auto getI = [&](int i, int j, bool flag){
        int idx = i*m + j;
        if(flag) idx += n*m;
        return idx;
    };

    int N = 2*n*m;
    vector<vector<pii>> g(N);
    for(i=0;i<n;i++){
        for(j=0;j<m-1;j++){
            int a; cin >> a;
            u = getI(i,j,false);
            if(j+1 < m){
                v = getI(i,j+1,false);
                g[u].push_back({v, a});
                g[v].push_back({u, a});
            }
        }
    }
    for(i=0;i<n-1;i++){
        for(j=0;j<m;j++){
            int b; cin >> b;
            u = getI(i,j,false);
            int uu = getI(i,j,true);
            if(i+1 < n){
                v = getI(i+1,j,false);
                g[u].push_back({v, b});
                int vv = getI(i+1,j,true);
                g[vv].push_back({uu,1});
            }
        }
    }
    for(i=0;i<n;i++){
        for(j=0;j<m;j++){
            u = getI(i,j,false);
            int uu = getI(i,j,true);
            g[u].push_back({uu, 1});
            g[uu].push_back({u, 0});
        }
    }

    int sv = getI(0,0,false);
    int tv = getI(n-1, m-1, false);
    auto ans = Dijkstra::solve(g, sv, tv);
    cout << ans[tv] << "\n";
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int nt = 1;
    for(int tt=1;tt<=nt;tt++){
        solve();
    }
    return 0;
}