#include<iostream>
#include<set>
#include<vector>
using namespace std;
typedef long long li;
#define rep(i,n) for(int i=0;i<(n);i++)
#define df 0
template<class T> void print(const T& t){ cout << t << "\n"; }
template<class T, class... Ts> void print(const T& t, const Ts&... ts) { cout << t; if (sizeof...(ts)) cout << " "; print(ts...); }

// Container コンテナ型, map以外
template< template<class ...> class Ctn,class T>
std::ostream& operator<<(std::ostream& os,const Ctn<T>& v){
  auto itr=v.begin();
  while(itr!=v.end()){
    if(itr!=v.begin())cout << " ";
    cout << *(itr++);
  }
  return os;
};

// pair 型
template<class S,class T>
std::ostream& operator<<(std::ostream& os, const pair<T,S>& p){
  cout << "(" << p.first << "," << p.second << ")";
  return os;
}

struct node{
  int v;
  li w;
  node(int vv=0,li ww=1){v=vv; w=ww;}
};


  
struct graph{
  int n;
  int m;
  int weighted,origin,directed;
  li ma;

  vector<vector<node>> adj;
  vector<li> col,w;
  graph(int nn,int mm,int d_flag=0,int w_flag=0,int ori=1){
    ma=0;
    n=nn; m=mm;
    weighted=w_flag;
    directed=d_flag;
    origin=ori;
    if(df){
      print(origin,"-origin");
      if(weighted) print("weighted");
      if(directed) print("directed");
    }
    adj.resize(n);
    rep(i,m){
      int a,b; li w=1; cin >>a >>b; a-=origin; b-=origin;
      if(weighted) cin >>w;
      adj[a].push_back({b,w});
      if(not directed)
        adj[b].push_back({a,w});
      ma=max(ma,w);
    }
  }
  void add(int a,int b,li w=1){
      adj[a].push_back({b,w});
      if(not directed)
        adj[b].push_back({a,w});
      ma=max(ma,w);
  }
  li dijkstra(int a,int b);
  li dijkstra(int b=-1){
    if(b==-1) b=n-1;
    return dijkstra(0,b);
  };

};

std::ostream& operator<<(std::ostream& os,const node& n){
  printf("%d[%ld]",n.v,n.w);
  return os;
};
std::ostream& operator<<(std::ostream& os,const graph& g){
  if(g.weighted){
    rep(i,g.n){
      printf("%d :",i+g.origin);
      for(auto p:g.adj[i]){
        printf(" %d[%d]",p.v+g.origin,p.w);
      }
      print("");
    }
  }else{
    rep(i,g.n){
      printf("%d :",i+g.origin);
      for(auto p:g.adj[i]){
        printf(" %d",p.v+g.origin);
      }
      print("");
    }
  }
  return os;
};


li graph::dijkstra(int a,int b){
  set<pair<li,int>> que;
  que.insert({a,0});
  vector<li> seen(n,ma*n+1);
  while(!que.empty()){
    auto p=*que.begin(); que.erase(que.begin());
    li d=p.first,v=p.second;
    if(df)print(v);
    if(v==b) return d;
    for(auto x:adj[v]){
      int u=x.v; li d0=x.w;
      if(d+d0<seen[u]){
        que.erase({seen[u],u});
        seen[u]=d+d0;
        que.insert({seen[u],u});
      }
    }
    if(df)print("que",que);
  }
  return ma*n+1;
}

int main(){
  int r,c; cin >>r >>c;
  graph g(r*c*2,0,1,1,0);
  rep(i,r)rep(j,c-1){
    li a; cin >>a;
    g.add(i*c+j,i*c+j+1,a);
    g.add(i*c+j+1,i*c+j,a);
  }
  rep(i,r-1)rep(j,c){
    li b; cin >>b;
    g.add(i*c+j,(i+1)*c+j,b);
  }
  rep(i,r)rep(j,c){
    g.add(i*c+j,r*c+i*c+j,1);
    g.add(r*c+i*c+j,i*c+j,0);
  }
  rep(i,r-1) rep(j,c){
    g.add(r*c+(i+1)*c+j,r*c+i*c+j,1);
  }
  if(df)print(g);
  print(g.dijkstra(r*c-1));
    
}

#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;

int n, m;
int a[510][510];
int b[510][510];
long long dist[510][510];
priority_queue<pair<long long, pair<int, int>>, vector<pair<long long, pair<int, int>>>, greater<pair<long long, pair<int, int>>>> pq;

bool in_range(int x, int y)
{
	return x >= 1 && x <= n && y >= 1 && y <= m;
}

int main()
{
	int i, j;
	int x, y;
	long long d;
	int nx, ny;
	long long nd;

	cin >> n >> m;
	for (i = 1; i <= n; i++)
	{
		for (j = 1; j < m; j++)
		{
			cin >> a[i][j];
		}
	}
	for (i = 1; i < n; i++)
	{
		for (j = 1; j <= m; j++)
		{
			cin >> b[i][j];
		}
	}

	memset(dist, 110, sizeof(dist));

	dist[1][1] = 0;
	pq.push(make_pair(0, make_pair(1, 1)));
	while (!pq.empty())
	{
		x = pq.top().second.first;
		y = pq.top().second.second;
		d = pq.top().first;
		pq.pop();

		if (dist[x][y] != d) continue;

		nx = x + 1;
		ny = y;
		if (in_range(nx, ny))
		{
			nd = d + b[x][y];
			if (dist[nx][ny] > nd)
			{
				dist[nx][ny] = nd;
				pq.push(make_pair(nd, make_pair(nx, ny)));
			}
		}

		nx = x;
		ny = y - 1;
		if (in_range(nx, ny))
		{
			nd = d + a[x][y - 1];
			if (dist[nx][ny] > nd)
			{
				dist[nx][ny] = nd;
				pq.push(make_pair(nd, make_pair(nx, ny)));
			}
		}

		nx = x;
		ny = y + 1;
		if (in_range(nx, ny))
		{
			nd = d + a[x][y];
			if (dist[nx][ny] > nd)
			{
				dist[nx][ny] = nd;
				pq.push(make_pair(nd, make_pair(nx, ny)));
			}
		}

		for (i = 1; i < x; i++)
		{
			nx = i;
			ny = y;
			nd = d + x - i + 1;
			if (dist[nx][ny] > nd)
			{
				dist[nx][ny] = nd;
				pq.push(make_pair(nd, make_pair(nx, ny)));
			}
		}
	}

	cout << dist[n][m];
}