#pragma gcc target("avx2")
#pragma gcc optimize("o3")
#pragma gcc optimize("unroll-loops")
//#pragma warning(disable : 4996)

//#define ATCODER
#ifdef ATCODER
#include <atcoder/all>
using namespace atcoder;
#endif

#include <limits.h>
#include <math.h>
#include <time.h>

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <complex>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

#if defined(LOCAL) || defined(_MSC_VER)
void debug_out() { cerr << endl; }

template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	cerr << " " << to_string(H);
	debug_out(T...);
}

#define DEBUG(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define DEBUG(...) 42
#endif

#ifdef _MSC_VER
#include <intrin.h>

#include "stdafx.h"
#define __builtin_popcount __popcnt
#define __builtin_popcountll __popcnt64
#endif

#define ll long long
#define REP(i, n) for (ll i = 0; i < (n); ++i)
#define REPR(i, n) for (ll i = (n)-1; i >= 0; --i)
#define FOR(i, m, n) for (ll i = (m); i < (n); ++i)
#define VSORT(v) sort(v.begin(), v.end());
#define VREVERSE(v) reverse(v.begin(), v.end())
#define print(x) cout << (x) << '\n'
#define spa << " " <<
#define lb(v, n) lower_bound(v.begin(), v.end(), (n))
#define ub(v, n) upper_bound(v.begin(), v.end(), (n))
//#define int long long
//#define double long double
#define all(x) (x).begin(), (x).end()
#define print_space(v) \
    REP(i, v.size()) cout << v[i] << " \n"[i == (int)v.size() - 1]
template <typename T1, typename T2>
inline bool chmin(T1& a, T2 b) {
	if (a > b) {
		a = b;
		return true;
	}
	return false;
}
template <typename T1, typename T2>
inline bool chmax(T1& a, T2 b) {
	if (a < b) {
		a = b;
		return true;
	}
	return false;
}
typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
std::random_device rd;
std::mt19937 mt(rd());
constexpr ll MOD = 1e9 + 7;
constexpr int MAX = 400040;
const double pi = acos(-1);
constexpr long double EPS = 1e-9;
const int dx[4] = { 0, 0, -1, 1 }, dy[4] = { -1, 1, 0, 0 };
using ld = long double;
const int INF = 1e9;
struct Dijkstra {
	using pii = pair<int, int>;
	struct edge {
		int to, cost;
		edge(int to_,int cost_):to(to_),cost(cost_){}
	};
	int N;
	vector<vector<edge>> G;
	vector<int> d;
	Dijkstra(int N_) : N(N_), G(N_), d(N_, INF) {}
	void add_edge(int u, int v, int c) { G[u].emplace_back( v, c ); }
	void build(int s) {
		d[s] = 0;
		priority_queue<pii, vector<pii>, greater<pii>> que;
		que.push(pii(0, s));
		while (!que.empty()) {
			pii 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.to] > d[v] + e.cost) {
					d[e.to] = d[v] + e.cost;
					que.push(pii(d[e.to], e.to));
				}
			}
		}
	}
};
int H, W;
int toid(int x, int y) { return x * W + y; }
int A[505][505], B[505][505];
void solve() {
	cin >> H >> W;
	REP(i, H) REP(j, W - 1) cin >> A[i][j];
	REP(i, H - 1) REP(j, W) cin >> B[i][j];
	int V = H * W;
	Dijkstra G(H * W);
	REP(i, H) REP(j, W) {
		if (j + 1 < W) { G.add_edge(toid(i, j), toid(i, j + 1), A[i][j]); }
		if (j - 1 >= 0) G.add_edge(toid(i, j), toid(i, j - 1), A[i][j - 1]);
		if (i + 1 < H) G.add_edge(toid(i, j), toid(i + 1, j), B[i][j]);
		REP(k, i) {
			G.add_edge(toid(i, j), toid(k, j), i - k + 1);
		}
	}
	G.build(toid(0, 0));
	print(G.d[H * W - 1]);
}

signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	// int q; cin >> q;
	// while (q--)
	solve();
}

#include <bits/stdc++.h>
using namespace std;

const int N = 500, D = 2 * 1000 * N;

vector<array<short, 2>> dijkstra[D];
int a[N][N], b[N][N], dist[N][N];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    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) {
        fill(dist[i], dist[i] + m, INT_MAX);
    }

    dijkstra[0].push_back({0, 0});
    dist[0][0] = 0;

    for (int d = 0; d < D; ++d) {
        while (!dijkstra[d].empty()) {
            auto [r, c] = dijkstra[d].back();
            dijkstra[d].pop_back();

            if (d > dist[r][c]) {
                continue;
            }

            if (c < m - 1 && d + a[r][c] < dist[r][c + 1]) {
                dist[r][c + 1] = d + a[r][c];
                dijkstra[dist[r][c + 1]].push_back({r, c + 1});
            }

            if (c > 0 && d + a[r][c - 1] < dist[r][c - 1]) {
                dist[r][c - 1] = d + a[r][c - 1];
                dijkstra[dist[r][c - 1]].push_back({r, c - 1});
            }

            if (r < n - 1 && d + b[r][c] < dist[r + 1][c]) {
                dist[r + 1][c] = d + b[r][c];
                dijkstra[dist[r + 1][c]].push_back({r + 1, c});
            }

            for (int i = 1; i <= r; ++i) {
                if (d + 1 + i < dist[r - i][c]) {
                    dist[r - i][c] = d + 1 + i;
                    dijkstra[dist[r - i][c]].push_back({r - i, c});
                }
            }
        }
    }

    cout << dist[n - 1][m - 1] << "\n";
}