#include<cstdio>
#include<queue>
#include<cstring>
#define N 3000010
#define M 9000150
using namespace std;
int n,m,ans,tot;
int src,dec,next[M],to[M],front[N],cap[M];
long long DIS[N];
struct edge
{
int number;
long long dis;
bool operator <(edge b) const
{
return dis>b.dis;
}
};
priority_queue<edge>q;
void add(int u,int v,int w)
{
to[++tot]=v;next[tot]=front[u];front[u]=tot;cap[tot]=w;
}
bool dijkstra()
{
for(int i=1;i<=dec;i++) DIS[i]=2e9;
q.push((edge){0,0});
while(!q.empty())
{
edge now=q.top();q.pop();
if(DIS[now.number]!=now.dis) continue;
for(int i=front[now.number];i;i=next[i])
{
if(DIS[to[i]]>DIS[now.number]+1ll*cap[i])
{
DIS[to[i]]=DIS[now.number]+1ll*cap[i];
q.push((edge){to[i],DIS[to[i]]});
}
}
}
printf("%d\n",DIS[dec]);
}
int main()
{
scanf("%d%d",&n,&m);
int x,l=2*m;
for(int i=1;i<=n;i++)
for(int j=1;j<m;j++)
{
scanf("%d",&x);
add((i-1)*l+1+(j-1)*2+1,(i-1)*l+1+(j-1)*2+1+l+1,x);
add((i-1)*l+1+(j-1)*2+1+l+1,(i-1)*l+1+(j-1)*2+1,x);
}
for(int i=1;i<n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&x);
add(i*l+(j-1)*2+1,i*l+(j-1)*2+1+1,x);
add(i*l+(j-1)*2+1+1,i*l+(j-1)*2+1,x);
}
for(int i=1;i<n;i++)
for(int j=1;j<m;j++)
{
scanf("%d",&x);
add(i*l+j*2,i*l+j*2+1,x);
add(i*l+j*2+1,i*l+j*2,x);
}
dec=(n+1)*l;
for(int i=l+1;i+l<=dec;i+=l) add(src,i,0);
for(int i=n*l+1;i<dec;i++) add(src,i,0);
for(int i=2;i<l;i+=2) add(i,dec,0);
for(int i=2*l;i+l<=dec;i+=l) add(i,dec,0);
dijkstra();
return 0;
}