#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c==‘-‘) f=-1;
for(;isdigit(c);c=Getchar()) x=x*10+c-‘0‘;
return x*f;
}
const int maxn=30010;
const int maxm=1000010;
const int inf=1e9;
struct ISAP{
struct tedge{int x,y,w,next;}adj[maxm];int ms,fch[maxn];
int d[maxn],s[maxn],cur[maxn],gap[maxn],n,top;
void init(int n){
this->n=n;ms=0;top=0;
memset(d,-1,sizeof(d));
memset(fch,-1,sizeof(fch));
return;
}
void AddEdge(int u,int v,int w){
adj[ms]=(tedge){u,v,w,fch[u]};fch[u]=ms++;
adj[ms]=(tedge){v,u,0,fch[v]};fch[v]=ms++;
return;
}
void bfs(){
queue<int>Q;Q.push(n);d[n]=0;
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int i=fch[u];i!=-1;i=adj[i].next){
int v=adj[i].y;
if(d[v]==-1) d[v]=d[u]+1,Q.push(v);
}
} return;
}
int solve(int S,int T){
n=T;bfs();int k=S,i,flow=0;
for(i=0;i<=n;i++) cur[i]=fch[i],gap[d[i]]++;
while(d[S]<n){
if(k==n){
int mi=inf,pos;
for(i=0;i<top;i++) if(adj[s[i]].w<mi) mi=adj[s[i]].w,pos=i;
for(i=0;i<top;i++) adj[s[i]].w-=mi,adj[s[i]^1].w+=mi;
flow+=mi;top=pos;k=adj[s[top]].x;
}
for(i=cur[k];i!=-1;i=adj[i].next){
int v=adj[i].y;
if(adj[i].w&&d[k]==d[v]+1){cur[k]=i;k=v;s[top++]=i;break;}
}
if(i==-1){
int lim=n;
for(i=fch[k];i!=-1;i=adj[i].next){
int v=adj[i].y;
if(adj[i].w&&d[v]<lim) lim=d[v],cur[k]=i;
} if(--gap[d[k]]==0) break;
d[k]=lim+1;gap[d[k]]++;
if(k!=S) k=adj[s[--top]].x;
}
} return flow;
}
}sol;
int n,m,sum,v;
int id(int x,int y,int t) {return t*n*m+(x-1)*m+y;}
const int mx[]={0,1,-1,0,0};
const int my[]={0,0,0,1,-1};
int main() {
n=read(),m=read();
int S=n*m*3+1,T=n*m*3+2;sol.init(T);
rep(i,1,n) rep(j,1,m) sol.AddEdge(S,id(i,j,0),v=read()),sum+=v;
rep(i,1,n) rep(j,1,m) sol.AddEdge(id(i,j,0),T,v=read()),sum+=v;
rep(i,1,n) rep(j,1,m) {
sol.AddEdge(S,id(i,j,1),v=read());sum+=v;
rep(dir,0,4) {
int nx=i+mx[dir],ny=j+my[dir];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m) sol.AddEdge(id(i,j,1),id(nx,ny,0),inf);
}
}
rep(i,1,n) rep(j,1,m) {
sol.AddEdge(id(i,j,2),T,v=read());sum+=v;
rep(dir,0,4) {
int nx=i+mx[dir],ny=j+my[dir];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m) sol.AddEdge(id(nx,ny,0),id(i,j,2),inf);
}
}
printf("%d\n",sum-sol.solve(S,T));
return 0;
}