#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using vl=vector<int>;
using vvl=vector<vl>;
using P=pair<int,int>;

const int INF=(1<<30);

struct graph{
    vvl edges;
    vvl cost;
    vl dist;
    graph(int n):edges(n), cost(n), dist(n, INF){}

    void add_edge(int from, int to, int c){
        edges[from].push_back(to);
        cost[from].push_back(c);
    }

    void dijkstra(int start){
        priority_queue<P,vector<P>,greater<P>> q;
        dist[start]=0;
        q.push(P(0,start));
        while (q.size()!=0)
        {
            P p=q.top();
            q.pop();
            int v=p.second;
            if(dist[v]<p.first)continue;
            for (int i = 0; i < edges[v].size(); i++){
                int to=edges[v][i];
                ll tmp_cost=dist[v]+cost[v][i];
                if(dist[to]>tmp_cost){
                    dist[to]=tmp_cost;
                    q.push(P(dist[to],to));
                }
            }
        }
    }
};
int R,C;
int id(int r, int c){return r*C + c;}
int main() {
    cin>>R>>C;
    int goal = id(R-1, C-1);
    vvl A(R, vl(C-1)), B(R-1, vl(C));
    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];

    graph g(R*C);
    for (int r = 0; r < R; r++){
        for (int c = 0; c < C; c++){
            if(c+1<C)g.add_edge(id(r,c), id(r,c+1), A[r][c]);
            if(c>0)g.add_edge(id(r,c), id(r,c-1), A[r][c-1]);
            if(r+1<R)g.add_edge(id(r,c), id(r+1,c), B[r][c]);
            for (int dr = 1; r-dr >= 0; dr++){
                g.add_edge(id(r,c), id(r-dr,c), dr+1);
            }
            // if(r>0)g.add_edge(id(r,c), id(r-1,c), 1);
        }
    }

    g.dijkstra(0);

    cout<<g.dist[goal]<<endl;
}
#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;
}