#pragma GCC optimize("O2")
#pragma GCC target("avx")
#include <cstdio>
#include <functional>
#include <queue>
#include <tuple>
#include <vector>
using namespace std;
using ll = long long;
#define shift 30

inline int get_digit() {
    int x = 0, f = 1;
    char c = getchar();
    while(c > '9' || c < '0') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x * 10) + (c ^ 48);
        c = getchar();
    }
    return x * f;
}

int main() {
    int R = get_digit(), C = get_digit();
    int A[250000], B[250000];
    int dist[500000], cost, pt, to_hide = R * C;
    vector<ll> s;
    s.reserve(2 * R * C);
    priority_queue<ll, vector<ll>, greater<ll>> queue(s.begin(), s.end());
    for(int i = 0; i < R * C; ++i) {
        if(i % C != C - 1) A[i] = get_digit();
        dist[i] = 0;
    }
    for(int i = 0; i < (R - 1) * C; ++i) B[i] = get_digit();
    dist[0] = -10000000;
    queue.push((ll)(-10000000) << shift);
    while(queue.size()) {
        pt = queue.top() & ((1 << shift) - 1);
        if(pt == to_hide - 1) break;
        cost = queue.top() >> shift;
        queue.pop();
        if(pt < to_hide) {
            if(pt % C != C - 1 & cost + A[pt] < dist[pt + 1]) {
                dist[pt + 1] = cost + A[pt];
                queue.push(((ll)dist[pt + 1] << shift) | (pt + 1));
            }
            if(pt % C != 0 & cost + A[pt - 1] < dist[pt - 1]) {
                dist[pt - 1] = cost + A[pt - 1];
                queue.push(((ll)dist[pt - 1] << shift) | (pt - 1));
            }
            if(pt < to_hide - C & cost + B[pt] < dist[pt + C]) {
                dist[pt + C] = cost + B[pt];
                queue.push(((ll)dist[pt + C] << shift) | (pt + C));
            }
            if(cost + 1 < dist[pt + to_hide]) {
                dist[pt + to_hide] = cost + 1;
                queue.push(((ll)dist[pt + to_hide] << shift) | (pt + to_hide));
            }
        } else {
            if(to_hide < pt - C && cost + 1 < dist[pt - C]) {
                dist[pt - C] = cost + 1;
                queue.push(((ll)(cost + 1) << shift) | (pt - C));
            }
            if(cost < dist[pt - to_hide]) {
                dist[pt - to_hide] = cost;
                queue.push(((ll)cost << shift) | (pt - to_hide));
            }
        }
    }
    printf("%d\n", dist[to_hide - 1] - dist[0]);
}
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mkp make_pair
#define pb push_back
#define sz(v) (int)(v).size()
typedef long long LL;
typedef double db;
template<class T>bool ckmax(T&x,T y){return x<y?x=y,1:0;}
template<class T>bool ckmin(T&x,T y){return x>y?x=y,1:0;}
#define rep(i,x,y) for(int i=x,i##end=y;i<=i##end;++i)
#define per(i,x,y) for(int i=x,i##end=y;i>=i##end;--i)
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
	return f?x:-x;
}
const int V = 1005;
const int N = 500005;
const int M = 12 * V * V;
struct edge {
	int nx, to, vl;
} e[M];
int hed[N], et;
inline void adde(int u, int v, int d) {
//	cerr << u << ' ' << v << ' ' << d << '\n';
	e[++et].nx = hed[u], e[et].to = v, e[et].vl = d, hed[u] = et;
}
int n, m, a[V][V], b[V][V], dis[N];
bool vis[N];
inline int id(int x, int y) {
	return (x - 1) * m + y;
}
inline void Dij() {
	priority_queue<pair<int, int> >pq;
	memset(dis, 0x3f, sizeof dis);
	pq.push(mkp(dis[1] = 0, 1));
	while(!pq.empty()) {
		int u = pq.top().se; pq.pop();
		if(vis[u]) continue;
		vis[u] = 1;
		for(int i = hed[u]; i; i = e[i].nx) {
			int v = e[i].to;
			if(ckmin(dis[v], dis[u] + e[i].vl)) {
				pq.push(mkp(-dis[v], v));
			}
		}
	}
}
signed main() {
	n = read(), m = read();
	rep(i, 1, n) rep(j, 1, m - 1) a[i][j] = read();
	rep(i, 1, n - 1) rep(j, 1, m) b[i][j] = read();
	rep(i, 1, n) {
		rep(j, 1, m - 1) {
			adde(id(i, j), id(i, j + 1), a[i][j]);
		}
		rep(j, 2, m) {
			adde(id(i, j), id(i, j - 1), a[i][j - 1]);
		}
		if(i < n) {
			rep(j, 1, m) adde(id(i, j), id(i + 1, j), b[i][j]);
		}
		rep(j, 1, m) {
			adde(id(i, j), id(i, j) + n * m, 1);
			adde(id(i, j) + n * m, id(i, j), 0);
			if(i > 1) adde(id(i, j) + n * m, id(i - 1, j) + n * m, 1);
		}
	}
	Dij();
	cout << dis[id(n, m)] << '\n';
}