#include<bits/stdc++.h>
#define mp make_pair
#define fi first
#define se second
#define VAL 100000
#define ll  long  long
#define INF 0x3f3f3f3f
#define pll pair<long long , long long>
const int MAX=5e6+9;
const ll mod=1e9+7;
const int TOT_PRIMES=19;
const int MAX_A=70;
using namespace std;
vector<pair<int , int > >adj[MAX];
bool check(int x, int y , int n , int m){
	if(x<0||y<0||x>=n||y>=m)
		return false;
	else
		return true;
}
int dijikstra(int n , int m){
	multiset<pair< int , int > > st;
	int dis[n*m+4];
	bool vis[n*m+4];
	for(int i = 0;i<n*m;i++){
		dis[i]=INF;
		vis[i]=false;
	}
	dis[0]=0;
	st.insert({0 , 0});
	while(!st.empty()){
		pair<int , int > it = *st.begin();
		int from = it.second;
		st.erase(st.begin());
	//	cout<<23;
		if(vis[from])
			continue;
		vis[from]=true;
		//cout<<from<<endl;
		for(auto v:adj[from]){
			if(dis[v.first]>=dis[from]+v.second){
				dis[v.first]=dis[from]+v.second;
				st.insert({dis[v.first],v.first});
			}
		}
	}
	return dis[(n)*m-1];
}
int main() 
{
	int n , m;
	cin>>n>>m;
	int a[n+1][m+1] , b[n+1][m+1];
	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(check(i , j+1, n , m)){
				adj[i*m+j].push_back({i*m+j+1 , a[i][j]});
			}
			if(check(i , j-1, n , m)){
				adj[i*m+j].push_back({i*m+j-1 , a[i][j-1]});
			}
			if(check(i+1 , j ,n , m)){
				adj[i*m+j].push_back({(i+1)*m+j , b[i][j]});
			}
			for(int k = 1;k<=n;k++){
				if(check(i-k , j, n , m)){
				adj[i*m+j].push_back({(i-k)*m+j , 1+k});
			}
			}
		}
	}
	cout<<dijikstra(n , m);

}

#include <bits/stdc++.h>

// #include <atcoder/all>
#define rep(i, s, t) for (int i = s; i < t; ++i)
using namespace std;
// using namespace atcoder;

using ll = long long;
using P = pair<int, int>;
constexpr int INF = (int)2e9;
constexpr ll INFll = (ll)1e18;
constexpr int MOD = 1e9 + 7;

struct edge {
  int to, cost;
  edge(int t, int c) : to(t), cost(c) {}
};

vector<vector<edge>> G;
int R, C;

int dijkstra(int s, int t) {
  priority_queue<P, vector<P>, greater<P>> que;
  vector<int> d(2 * R * C, INF);

  que.emplace(s, 0);
  d[s] = 0;

  while (!que.empty()) {
    auto p = que.top();
    que.pop();
    int curd = p.first, curv = p.second;
    if (curd > d[curv]) continue;
    for (auto e : G[curv]) {
      if (curd + e.cost < d[e.to]) {
        d[e.to] = curd + e.cost;
        que.emplace(d[e.to], e.to);
      }
    }
  }
  return d[t];
}

int main() {
  cin >> R >> C;
  G.resize(2 * R * C);
  rep(r, 0, R) rep(c, 0, C - 1) {
    int a;
    cin >> a;
    G[r * C + c].emplace_back(r * C + c + 1, a);
    G[r * C + c + 1].emplace_back(r * C + c, a);
  }
  rep(r, 0, R - 1) rep(c, 0, C) {
    int b;
    cin >> b;
    G[r * C + c].emplace_back((r + 1) * C + c, b);
  }
  rep(r, 0, R) rep(c, 0, C) {
    G[r * C + c].emplace_back(r * C + c + R * C, 1);
    G[r * C + c + R * C].emplace_back(r * C + c, 0);
  }
  rep(r, 0, R - 1) rep(c, 0, C) {
    G[(r + 1) * C + c + R * C].emplace_back(r * C + c + R * C, 1);
  }

  cout << dijkstra(0, R * C - 1) << endl;
}