#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using pll = pair<ll, ll>;
constexpr ll MOD = 1e9 + 7;
//constexpr ll MOD = 998244353;
//constexpr ll MOD = ;
ll mod(ll A, ll M) {return (A % M + M) % M;}
constexpr ll INF = 1LL << 60;
template<class T> bool chmin(T& a, T b) {if (a > b) {a = b; return true;} return false;}
template<class T> bool chmax(T& a, T b) {if (a < b) {a = b; return true;} return false;}
ll divceil(ll A, ll B) {return (A + (B - 1)) / B;}
#define FINALANS(A) do {cout << (A) << '\n'; exit(0);} while (false)

class graph
{
public:
  struct edge
  {
    ll to, cost;
    edge(ll to, ll cost) : to(to), cost(cost) {}

    bool operator<(const edge &right) const
    {
      return cost < right.cost;
    }

    bool operator>(const edge &right) const
    {
      return cost > right.cost;
    }
  };

  ll N;
  vector<vector<edge>> G;

  graph(ll n)
  {
    N = n;
    G.resize(N);
  }

  void connect(ll sv, ll gv, ll c)
  {
    G.at(sv).push_back(edge(gv, c));
  }

  void connect2(ll v0, ll v1, ll c)
  {
    connect(v0, v1, c), connect(v1, v0, c);
  }

  void dijkstra(ll sv, vector<ll> &costs)
  {
    costs = vector<ll>(N, INF);
    costs.at(sv) = 0;
    priority_queue<pll, vector<pll>, greater<pll>> pque;
    for (auto e : G.at(sv))
    {
      pque.push(make_pair(e.cost, e.to));
    }

    while (!pque.empty())
    {
      pll cv = pque.top();
      ll c = cv.first, v = cv.second;
      pque.pop();

      if (costs.at(v) != INF)
        continue;
      costs.at(v) = c;

      for (auto e : G.at(v))
      {
        if (costs.at(e.to) != INF)
          continue;

        pque.push(make_pair(c + e.cost, e.to));
      }
    }
  }
};

ll R, C;

ll tptol(ll r, ll c, ll b)
{
  return 2 * (R * c + r) + b;
}

int main()
{
  cin >> R >> C;
  vector<vector<ll>> A(R, vector<ll>(C - 1));
  for (ll i = 0; i < R; i++)
  {
    for (ll j = 0; j < C - 1; j++)
    {
      cin >> A.at(i).at(j);
    }
  }
  vector<vector<ll>> B(R - 1, vector<ll>(C));
  for (ll i = 0; i < R - 1; i++)
  {
    for (ll j = 0; j < C; j++)
    {
      cin >> B.at(i).at(j);
    }
  }

  graph gr(2 * R * C);
  for (ll r = 0; r < R; r++)
  {
    for (ll c = 0; c < C - 1; c++)
    {
      gr.connect(tptol(r, c, 0), tptol(r, c + 1, 0), A.at(r).at(c));
      //cerr << r << " " << c << " " << r << " " << c + 1 << " " << A.at(r).at(c) << endl;
    }
  }
  for (ll r = 0; r < R; r++)
  {
    for (ll c = 1; c < C; c++)
    {
      gr.connect(tptol(r, c, 0), tptol(r, c - 1, 0), A.at(r).at(c - 1));
      //cerr << r << " " << c << " " << r << " " << c - 1 << " " << A.at(r).at(c - 1) << endl;
    }
  }
  for (ll r = 0; r < R - 1; r++)
  {
    for (ll c = 0; c < C; c++)
    {
      gr.connect(tptol(r, c, 0), tptol(r + 1, c, 0), B.at(r).at(c));
      //cerr << r << " " << c << " " << r + 1 << " " << c << " " << B.at(r).at(c) << endl;
    }
  }

  for (ll r = 0; r < R; r++)
  {
    for (ll c = 0; c < C; c++)
    {
      gr.connect(tptol(r, c, 0), tptol(r, c, 1), 0);
      gr.connect(tptol(r, c, 1), tptol(r, c, 0), 1);
    }
  }
  for (ll r = 1; r < R; r++)
  {
    for (ll c = 0; c < C; c++)
    {
      gr.connect(tptol(r, c, 1), tptol(r - 1, c, 1), 1);
    }
  }

  vector<ll> costs;
  gr.dijkstra(0, costs);

  ll ans = costs.at(tptol(R - 1, C - 1, 0));
  cout << ans << endl;
}
#include<cstdio>
#include<queue>
#define F(i,l,r) for(int i=l,i##_end=r;i<i##_end;++i)
using namespace std;
const int N=505,INF=0x3fffffff;
template<typename T>void read(T &x)
{
	bool neg=false;
	unsigned char c=getchar();
	for(;(c^48)>9;c=getchar())if(c=='-')neg=true;
	for(x=0;(c^48)<10;c=getchar())x=(x<<3)+(x<<1)+(c^48);
	if(neg)x=-x;
}
struct node
{
	int x,y,d;
	bool operator<(node b)const{return b.d<d;}
}n1,n2;
int n,m,a[N][N],b[N][N],dis[N][N];
priority_queue<node> q;
int main()
{
	read(n);read(m);
	F(i,0,n)F(j,0,m-1)read(a[i][j]);
	F(i,0,n-1)F(j,0,m)read(b[i][j]);
	F(i,0,n)F(j,0,m)dis[i][j]=INF;
	dis[0][0]=0;
	n1.x=n1.y=n1.d=0;
	q.push(n1);
	while(!q.empty())
	{
		int x,y,d;
		n1=q.top();q.pop();
		if(dis[x=n1.x][y=n1.y]!=(d=n1.d))continue;
		if(x<n)if(dis[x+1][y]>dis[x][y]+b[x][y])
		{
			dis[x+1][y]=dis[x][y]+b[x][y];
			n2.x=x+1;n2.y=y;n2.d=dis[x+1][y];
			q.push(n2);
		}
		F(i,0,x)if(dis[i][y]>dis[x][y]+x-i+1)
		{
			dis[i][y]=dis[x][y]+x-i+1;
			n2.x=i;n2.y=y;n2.d=dis[i][y];
			q.push(n2);
		}
		if(y&&dis[x][y-1]>dis[x][y]+a[x][y-1])
		{
			dis[x][y-1]=dis[x][y]+a[x][y-1];
			n2.x=x;n2.y=y-1;n2.d=dis[x][y-1];
			q.push(n2);
		}
		if(y<m&&dis[x][y+1]>dis[x][y]+a[x][y])
		{
			dis[x][y+1]=dis[x][y]+a[x][y];
			n2.x=x;n2.y=y+1;n2.d=dis[x][y+1];
			q.push(n2);
		}
	}
	printf("%d\n",dis[n-1][m-1]);
	return 0;
}
