#include "bits/stdc++.h"
using namespace std;
#define ll long long

#define       forn(i,n)              for(int i=0;i<n;i++)
#define          all(v)              v.begin(), v.end()
#define         rall(v)              v.rbegin(),v.rend()
 
#define            pb                push_back
#define          sz(a)               (int)a.size()
#define         fastio               ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define      GR(a,n,m)               vector<vector<int>> a(n, vector<int>(m, 0));

const int N = 505;
int A[N][N], B[N][N], n, m;
bool vis[N][N];
int dist[N][N];

vector<pair<pair<int,int>,int>> adj[N][N];
void solve()
{
	cin >> n >> m;

	for(int i = 0;i < n;i++)
	{
		for(int j = 0;j < m - 1;j++){
			cin >> A[i][j];
		}
	}
	for(int i = 0;i < n - 1;i++){
		for(int j = 0;j < m;j++){
			cin >> B[i][j];
		}
	}

	for(int i = 0;i < n;i++)
	{
		for(int j = 0;j < m;j++)
		{
			if(i + 1 < n){
				adj[i][j].pb({{i + 1,j},B[i][j]});
			}
			if(j + 1 < m){
				adj[i][j].pb({{i,j + 1},A[i][j]});
			}
			if(j - 1 >= 0){
				adj[i][j].pb({{i,j - 1}, A[i][j - 1]});
			}
		}
	}

	for(int r = 0;r < n;r++)
	{
		for(int c = 0;c < m;c++)
		{
			for(int i = 1;i <= r;i++)
			{
				adj[r][c].pb({{r - i, c}, i + 1});
			}
		}
	}
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++)
			dist[i][j] = INT_MAX;
	dist[0][0] = 0;
	int k = 1000;
	queue<pair<int,int>> q[k + 5];
	int cnt = 1, pos = 0;
	q[0].push({0,0});
	while(cnt > 0)
	{
		while(q[pos % (k + 1)].empty())++pos;
		int x = q[pos % (k + 1)].front().first, y = q[pos % (k + 1)].front().second;
		q[pos % (k + 1)].pop();
		--cnt;
		if(vis[x][y])continue;
		vis[x][y] = true;

		for(auto v : adj[x][y])
		{
			int i = v.first.first, j = v.first.second, w = v.second;
			if(dist[x][y] + w < dist[i][j])
			{
				dist[i][j] = dist[x][y] + w;
				q[dist[i][j] % (k + 1)].push({i,j});
				++cnt;
			}
		}
	}
	cout << dist[n - 1][m - 1] << "\n";
}

 
int32_t main()
{
	fastio;
	int t = 1;
	//cin >> t;
	for(int tt = 0;tt < t;tt++)
	{
		solve();
	}
}
#pragma GCC optimize("O2")
#pragma GCC target("avx")
#include <cstdio>
#include <functional>
#include <queue>
#include <tuple>
using namespace std;

inline int_fast32_t get_digit() {
    int_fast32_t 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_fast32_t R, C;
    scanf("%d%d", &R, &C);
    int_fast32_t A[250000], B[250000];
    int_fast32_t dist[500000], seen[500000] = {0}, cost, pt, to_hide = R * C;
    priority_queue<pair<int_fast32_t, int_fast32_t>, vector<pair<int_fast32_t, int_fast32_t>>,
                   greater<pair<int_fast32_t, int_fast32_t>>>
        queue;
    for(int_fast32_t i = 0; i < R * C; ++i)
        if(i % C != C - 1) A[i] = get_digit();
    for(int_fast32_t i = 0; i < (R - 1) * C; ++i) B[i] = get_digit();
    for(int_fast32_t i = 1; i < to_hide + to_hide; ++i) dist[i] = 10000000;
    queue.emplace(pair<int_fast32_t, int_fast32_t>(0, 0));
    while(!queue.empty()) {
        tie(cost, pt) = queue.top();
        if(pt == to_hide - 1) break;
        queue.pop();
        seen[pt] = true;
        if(pt < to_hide) {
            if(!seen[pt + 1] && pt % C != C - 1) {
                if(cost + A[pt] < dist[pt + 1]) {
                    dist[pt + 1] = cost + A[pt];
                    queue.emplace(pair<int_fast32_t, int_fast32_t>(dist[pt + 1], pt + 1));
                }
            }
            if(!seen[pt - 1] && pt % C != 0) {
                if(cost + A[pt - 1] < dist[pt - 1]) {
                    dist[pt - 1] = cost + A[pt - 1];
                    queue.emplace(pair<int_fast32_t, int_fast32_t>(dist[pt - 1], pt - 1));
                }
            }
            if(!seen[pt + C] && pt < to_hide - C) {
                if(cost + B[pt] < dist[pt + C]) {
                    dist[pt + C] = cost + B[pt];
                    queue.emplace(pair<int_fast32_t, int_fast32_t>(dist[pt + C], pt + C));
                }
            }
            if(!seen[pt + to_hide] && cost + 1 < dist[pt + to_hide]) {
                dist[pt + to_hide] = cost + 1;
                queue.emplace(pair<int_fast32_t, int_fast32_t>(dist[pt + to_hide], pt + to_hide));
            }
        } else {
            if(to_hide < pt - C && !seen[pt - C] && cost + 1 < dist[pt - C]) {
                dist[pt - C] = cost + 1;
                queue.emplace(pair<int_fast32_t, int_fast32_t>(cost + 1, pt - C));
            }
            if(!seen[pt - to_hide] && cost < dist[pt - to_hide]) {
                dist[pt - to_hide] = cost;
                queue.emplace(pair<int_fast32_t, int_fast32_t>(cost, pt - to_hide));
            }
        }
    }
    printf("%d\n", dist[to_hide - 1]);
}