#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <cmath>
#include <iomanip>
#include <stack>
#include <queue>
#include <numeric>
#include <map>
#include <unordered_map>
#include <set>
#include <fstream>
#include <chrono>
#include <random>
#include <bitset>
//#include <atcoder/all>
#define rep(i,n) for(int i=0;i<(n);i++)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) ((int)(x).size())
#define pb push_back
using ll = long long;
using namespace std;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
ll gcd(ll a, ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a, ll b) {return a/gcd(a,b)*b;}
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;

#define n50 250000

int f(int r,int c){
  return r*500+c;
}

int main(){
  int R,C; cin >> R >> C;
  vvi g(n50);
  vvi co(n50);
  rep(r,R) rep(c,C-1){
    int in; cin >> in;
    int ff=f(r,c);
    g[ff].pb(ff+1);
    g[ff+1].pb(ff);
    co[ff].pb(in);
    co[ff+1].pb(in);
  }
  rep(r,R-1) rep(c,C){
    int in; cin >> in;
    int ff=f(r,c);
    g[ff].pb(ff+500);
    co[ff].pb(in);
  }
  rep(c,C){
    rep(r,R){
      rep(s,r){
        int ff=f(r,c);
        g[ff].pb(f(s,c));
        co[ff].pb(r-s+1);
      }
    }
  }
  vector<int> D(n50, 1e9);
  vector<bool> used(n50, false);
  priority_queue<pair<int,int>,
                 vector<pair<int,int>>,
                 greater<pair<int,int>>> q;
  q.push({0,0});
  while(!q.empty()){
    int d = q.top().first; int to = q.top().second; q.pop();
    if(used[to]) continue;
    used[to] = true; D[to] = d;
    rep(i,sz(g[to])){
      int nxt=g[to][i];
      int nd = D[to] + co[to][i];
      if(D[nxt] <= nd) continue;
      D[nxt] = nd;
      q.push({nd, nxt});
    }
  }

  int ans = D[f(R-1,C-1)];
  cout << ans << endl;
  return 0;
}

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	int r, c;
	cin >> r >> c;

	vector <vector<int>> a(r + 1, vector <int> (c + 1, 0));
	for(int i = 1; i <= r; i++) {
		for(int j = 1; j < c; j++) {
			cin >> a[i][j];
		}
	}

	vector <vector<int>> b(r + 1, vector <int> (c + 1, 0));
	for(int i = 1; i < r; i++) {
		for(int j = 1; j <= c; j++) {
			cin >> b[i][j];
		}
	}

	auto Dijkstra = [&] (pair <int, int> src, pair<int, int> dst) -> int {
		vector <vector<int>> dist(r + 1, vector <int> (c + 1, 1e9));

		using tup = tuple <int, int, int>;
		priority_queue <tup, vector<tup>, greater<tup>> pq;

		dist[src.first][src.second] = 0;
		pq.emplace(0, src.first, src.second);

		while(!pq.empty()) {
			auto [cost, x, y] = pq.top();
			pq.pop();

			if(dist[x][y] < cost) continue;

			{
				int nx = x, ny = y + 1;
				if(nx >= 1 && nx <= r && ny >= 1 && ny <= c && dist[nx][ny] > dist[x][y] + a[x][y]) {
					dist[nx][ny] = dist[x][y] + a[x][y];
					pq.emplace(dist[nx][ny], nx, ny);
				}
			}

			{
				int nx = x, ny = y - 1;
				if(nx >= 1 && nx <= r && ny >= 1 && ny <= c && dist[nx][ny] > dist[x][y] + a[x][y - 1]) {
					dist[nx][ny] = dist[x][y] + a[x][y - 1];
					pq.emplace(dist[nx][ny], nx, ny);
				}
			}

			{
				int nx = x + 1, ny = y;
				if(nx >= 1 && nx <= r && ny >= 1 && ny <= c && dist[nx][ny] > dist[x][y] + b[x][y]) {
					dist[nx][ny] = dist[x][y] + b[x][y];
					pq.emplace(dist[nx][ny], nx, ny);
				}
			}

			{
				for(int i = 1; i < x; i++) {
					int nx = x - i, ny = y;
					if(nx >= 1 && nx <= r && ny >= 1 && ny <= c && dist[nx][ny] > dist[x][y] + 1 + i) {
						dist[nx][ny] = dist[x][y] + 1 + i;
						pq.emplace(dist[nx][ny], nx, ny);
					}
				}
			}
		}
		return dist[dst.first][dst.second];
	};

	pair <int, int> src = make_pair(1, 1);
	pair <int, int> dst = make_pair(r, c);
	cout << Dijkstra(src, dst);
}