#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
const int MXlim = 1048580;
int lim, n, m;
int f[MXlim];
bool vis[MXlim] = {false};
int a[12][12], b[12][12];
queue <int> q;
int popcnt(int x) {
int res = 0;
while(x) res += (x & 1), x >>= 1;
return res;
}
int pupcnt(int x){
int res = 0;
while(x) res += ((x & 1) ^ 1), x >>= 1;
return res;
}
int poopcnt(int x);
int upto0(int x) {
return (x < 0 ? 0 : x);
}
void bit_opt(int x){
string str = "";
int cnt = 0;
while(cnt++ < n + m) {
if(x & 1) str += "1";
else str += "0";
x >>= 1;
}
reverse(str.begin(), str.end());
cout << str << '\n';
}
void faq(int x) {
int lst = -1, bkw = 0, cnt = 0;
while(cnt < n + m) {
int tmp = x & 1;
if(lst == 1 && tmp == 0) {
int ans = (((x << 1) + 1) << (cnt - 1)) + bkw;
q.push(ans);
vis[ans] = true;
int X = n - pupcnt(x | (1 << (n + m - cnt))) + 1;
int y = popcnt(x) + 1;
if(poopcnt(ans) & 1)
f[ans] = max(f[ans], f[(x << cnt) | bkw] + a[X][y]);
else
f[ans] = min(f[ans], f[(x << cnt) | bkw] - b[X][y]);
}
bkw |= (tmp << cnt);
lst = tmp;
cnt++;
x >>= 1;
}
}
int poopcnt(int x) {
int tmp = n, res = 0;
while(tmp) {
if(x & 1) res += tmp;
else tmp--;
x >>= 1;
}
return n * m - res;
}
int main() {
cin >> n >> m;
lim = (1 << (n + m)) - 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cin >> a[i][j];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cin >> b[i][j];
q.push((1 << m) - 1);
f[q.front()] = 0;
while(!q.empty()) {
int now = q.front();
q.pop();
faq(now);
}
cout << f[((1 << m) - 1) << n];
return 0;
}