#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <cmath>
#include <iomanip>
#include <stack>
#include <queue>
#include <numeric>
#include <map>
#include <unordered_map>
#include <set>
#include <fstream>
#include <chrono>
#include <random>
#include <bitset>
//#include <atcoder/all>
#define rep(i,n) for(int i=0;i<(n);i++)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) ((int)(x).size())
#define pb push_back
using ll = long long;
using namespace std;
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; }
ll gcd(ll a, ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a, ll b) {return a/gcd(a,b)*b;}
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vl = vector<ll>;
using vvl = vector<vl>;
using vvvl = vector<vvl>;

int f(int b,int r,int c){
  return b*500*500+r*500+c;
}

int main(){
  int R,C; cin >> R >> C;
  vvi g(500*500*2);
  vvi co(500*500*2);
  rep(r,R) rep(c,C-1){
    int in; cin >> in;
    g[f(0,r,c)].pb(f(0,r,c+1));
    g[f(0,r,c+1)].pb(f(0,r,c));
    co[f(0,r,c)].pb(in);
    co[f(0,r,c+1)].pb(in);
  }
  rep(r,R-1) rep(c,C){
    int in; cin >> in;
    g[f(0,r,c)].pb(f(0,r+1,c));
    co[f(0,r,c)].pb(in);
  }
  rep(r,R-1) rep(c,C){
    g[f(1,r+1,c)].pb(f(1,r,c));
    co[f(1,r+1,c)].pb(1);
  }
  rep(r,R) rep(c,C){
    g[f(0,r,c)].pb(f(1,r,c));
    co[f(0,r,c)].pb(1);
    g[f(1,r,c)].pb(f(0,r,c));
    co[f(1,r,c)].pb(0);
  }
  vector<int> D(500*500*2, -1);
  vector<bool> used(500*500*2, false);
  priority_queue<pair<int,int>,
                 vector<pair<int,int>>,
                 greater<pair<int,int>>> q;
  q.push({(int)0,f(0,0,0)});
  D[0]=0;
  while(!q.empty()){
    int d = q.top().first; int to = q.top().second; q.pop();
    if(used[to]) continue;
    used[to] = true; //D[to] = d;
    rep(i,sz(g[to])){
      int nxt=g[to][i];
      int nd = d+co[to][i];
      if(D[nxt] != -1 && D[nxt] <= nd) continue;
      D[nxt]=nd;
      q.push({nd, nxt});
    }
  }

  int ans = D[f(0,R-1,C-1)];
  cout << ans << endl;
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define int long long
using vec_int = vector<int>;
using P = pair<int,int>;
using T = tuple<int,int,int>;
using T2 = tuple<int,int,int, int>;
using ll = long long;
#define rep(i, n) for(int i = 0; i < (int)(n); i++)

int charToInt(char c){
    char zero_num = '0';
    return (int)c - (int)zero_num;
}

signed main(){

    int R, C; cin>>R>>C;
    vector<vec_int> A(R, vec_int(C-1));
    rep(i,R)rep(j,C-1)cin>>A.at(i).at(j);

    vector<vec_int> B(R-1, vec_int (C));
    rep(i,R-1)rep(j,C)cin>>B.at(i).at(j);

    vector<vec_int> visited(R, vec_int(C, 0));

    priority_queue<T2, vector<T2>, greater<T2>> pq;
    pq.emplace(0, 0, 0, 0);



    while(!pq.empty()){
        int cost, r, c, type; tie(cost, r, c, type)=pq.top(); pq.pop();
        if(visited.at(r).at(c)==1)continue;
        if(r==R-1&&c==C-1){
            cout<<cost<<endl;
            return 0;
        }
        visited.at(r).at(c) = 1;
        if(c<C-1){
            if(visited.at(r).at(c+1)==0){
                pq.emplace(cost+A.at(r).at(c), r, c+1, 1);
            }
        }
        if(c>0){
            if(visited.at(r).at(c-1)==0){
                pq.emplace(cost+A.at(r).at(c-1), r, c-1, 1);
            }
        }
        if(r<R-1){
            if(visited.at(r+1).at(c)==0){
                pq.emplace(cost+B.at(r).at(c), r+1, c, 0);
            }
        }
        if(type==1){
            for(int i=0;i<r;i++){
                if(visited.at(i).at(c)==0){
                    pq.emplace(cost+(r-i+1), i, c, 0);
                }
            }
        }
    }





    return 0;
}