#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;i++)
#define cinf(n,x) for(int i=0;i<(n);i++)cin>>x[i];
#define ft first
#define sc second
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define all(v) (v).begin(),(v).end()
#define LB(a,x) lb(all(a),x)-a.begin()
#define UB(a,x) ub(all(a),x)-a.begin()
#define mod 1000000007
//#define mod 998244353
#define FS fixed<<setprecision(15)
using namespace std;
typedef long long ll;
const double pi=3.141592653589793;
template<class T> using V=vector<T>;
using P=pair<ll,ll>;
typedef unsigned long long ull;
typedef long double ldouble;
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline void out(T a){ cout << a << '\n'; }
void YN(bool ok){if(ok) cout << "Yes" << endl; else cout << "No" << endl;}
//void YN(bool ok){if(ok) cout << "YES" << endl; else cout << "NO" << endl;}


const ll INF=1e18;
const int mx=200005;
//zone

ll a[502][502];
ll b[502][502];


ll dp[502][502];
int main(){
    //オーバーフローは大丈夫ですか？？
    cin.tie(0);ios::sync_with_stdio(false);
    ll R,C;
    cin>>R>>C;
    rep(i,R)rep(j,C-1) cin>>a[i][j];
    rep(i,R-1)rep(j,C) cin>>b[i][j];
    rep(i,R)rep(j,C) dp[i][j]=INF;
    dp[0][0]=0;
    priority_queue<pair<ll,P>,V<pair<ll,P>>,greater<pair<ll,P>>> que;
    que.push({0,{0,0}});
    while(que.size()){
        pair<ll,P> p=que.top();
        que.pop();
        int i=p.sc.ft;
        int j=p.sc.sc;
        if(dp[i][j]<p.ft) continue;
        if(j+1<C){
            if(chmin(dp[i][j+1],dp[i][j]+a[i][j])){
                que.push({dp[i][j+1],{i,j+1}});
            }
        }
        if(j-1>=0){
            if(chmin(dp[i][j-1],dp[i][j]+a[i][j-1])){
                que.push({dp[i][j-1],{i,j-1}});
            }
        }
        if(i+1<R){
            if(chmin(dp[i+1][j],dp[i][j]+b[i][j])){
                que.push({dp[i+1][j],{i+1,j}});
            }
        }
        for(int k=0;k<i;k++){
            if(chmin(dp[k][j],dp[i][j]+(ll)i-k+1)){
                que.push({dp[k][j],{k,j}});
            }
        }
        //cout<<i<<' '<<j<<endl;
    }
    out(dp[R-1][C-1]);
}
//E
//ペナルティ出しても焦らない　ACできると信じろ！！！
//どうしてもわからないときはサンプルで実験　何か見えてくるかも
//頭で考えてダメなら紙におこせ！！
//添字注意！！(特に多重ループのとき)
#include <bits/stdc++.h>
using namespace std;
 
#define REP(i, s) for (int i = 0; i < s; ++i)
#define ALL(v) (v).begin(), (v).end()
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)
#define DEBUG
//#define int long long
#define INF 1e18
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ EACH(it, P) { s << "<" << *it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s << endl; }
template<class T>void show(vector<T>v){for (int i = 0; i < v.size(); i++){cerr<<v[i]<<" ";}cerr<<"\n";}
typedef long long ll;

using Edge = pair<int, int>;
using Graph = vector<vector<Edge>>;

Graph G;
int n, d[250010];

// <最短距離, 頂点の番号>
using P = pair<int, int>;

void dijkstra(int s)
{
    priority_queue<P, vector<P>, greater<P>> que;
    fill(d, d + n, INF);
    d[s] = 0;
    que.push(P(0, s));

    while (!que.empty())
    {
        P p = que.top();
        que.pop();
        int v = p.second;
        if (d[v] < p.first)
            continue;

        for (int i = 0; i < G[v].size(); ++i)
        {
            Edge e = G[v][i];
            if (d[e.first] > d[v] + e.second)
            {
                d[e.first] = d[v] + e.second;
                que.push(P(d[e.first], e.first));
            }
        }
    }
}

int a[510][510];
int b[510][510];
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int r,c;
    cin>>r>>c;
    n=r*c;
    G.assign(r*c , vector<Edge>());
    for (int i = 0; i < r; i++)
    {
        for (int j = 0; j < c-1; j++)
        {
            cin>>a[i][j];
        }
        
    }
    for (int i = 0; i < r-1; i++)
    {
        for (int j = 0; j < c; j++)
        {
            cin>>b[i][j];
            
        }
        
    }
    
    for (int i = 0; i < r; i++)
    {
        for (int j = 0; j < c; j++)
        {
            
            if(j<c-1) G[c*i + j].push_back({c*i+j+1, a[i][j]});
            if(j>=1) G[c*i + j].push_back({c*i+j-1, a[i][j-1]});
            if(i<r-1) G[c*i + j].push_back({c*(i+1)+j, b[i][j]});
        }
        
    }
    for (int i = 0; i < r; i++)
    {
        for (int j = 0; j < c; j++)
        {
            for (int k = 1; k < r; k++)
            {
                if(i - k < 0 ) continue;
                G[c*i+j].push_back({c*i+j - c*k , 1 + k});
            }
            
        }
        
    }
    dijkstra(0);
    cout<<d[r*c-1]<<endl;
    
    
    return 0;
}