#pragma clang optimize on
#include <cstdio>
#include <functional>
#include <iostream>
#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]);
}
//For higher stack size use g++ -O2 -std=c++11 -Wall -Wl,--stack=268435456 a.cpp -o a.exe in cmd
#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstring>
#include <chrono>
#include <complex>
#define ll long long int
#define ld long double
#define vi vector<int>
#define vll vector<ll>
#define vvi vector < vi >
#define pii pair<int,int>
#define pll pair<long long, long long>
#define mod 1000000007
#define inf 1000000000000000001;
#define all(c) c.begin(),c.end()
#define mp(x,y) make_pair(x,y)
#define mem(a,val) memset(a,val,sizeof(a))
#define eb emplace_back
#define pb push_back
#define f first
#define s second

using namespace std;
int main()
{
	std::ios::sync_with_stdio(false);
	int T;
	T=1;
	// cin.ignore(); must be there when using getline(cin, s)
	while(T--)
	{
		int n,m,i,j;
		cin>>n>>m;
		int ar[n+1][m+1],ar2[n+1][m+1],ar3[m+1],pos[m+1];
		for(i=1;i<=n;++i)
		{
			for(j=1;j<=m-1;++j)
			{
				cin>>ar[i][j];
			}
		}
		for(i=1;i<=n-1;++i)
		{
			for(j=1;j<=m;++j)
			{
				cin>>ar2[i][j];
			}
		}
		int ans[n+1][m+1],flag=0;
		for(i=1;i<=n;++i)
		{
			for(j=1;j<=m;++j)
			{
				ans[i][j]=1e9;
			}
		}
		ans[n][m]=0;
		start:
		for(j=m-1;j>0;--j)
		{
			ans[n][j]=min(ans[n][j],ans[n][j+1]+ar[n][j]);
		}
		
		for(i=n-1;i>=1;--i)
		{
			for(j=m;j>=1;--j)
			{
				ans[i][j]=min(ans[i][j],ans[i+1][j]+ar2[i][j]);
			}
			for(j=m-1;j>=1;--j)
			{
				ans[i][j]=min(ans[i][j],ans[i][j+1]+ar[i][j]);
			}
			for(j=2;j<=m;++j)
			{
				ans[i][j]=min(ans[i][j],ans[i][j-1]+ar[i][j-1]);
			}
		}
		++flag;
		if(flag<=max(n,m)+10)
		{
			for(j=1;j<=m;++j)
			{
				ar3[j]=ans[1][j];
				pos[j]=1;
			}
			for(i=2;i<=n;++i)
			{
				for(j=1;j<=m;++j)
				{
					ans[i][j]=min(ans[i][j],ar3[j]+1+(i-pos[j]));
					if(ans[i][j]<=ar3[j]+(i-pos[j]))
					{
						ar3[j]=ans[i][j];
						pos[j]=i;
					}
				}
			}
			goto start;
		}
		cout<<ans[1][1]<<endl;
	}
	return 0;
}