CodeEff/ECCO huggingface dataset:
# Original solution

def resolve():
    H, W = map(int, input().split())
    A = [tuple(map(int, input().split())) for _ in range(H)]
    B = [tuple(map(int, input().split())) for _ in range(H)]

    # 移動直前の偏りをkとし、移動先のマス(i, j)
    # についてd = abs(A[i][j] - B[i][j])
    # とした際に、移動後の偏りをabs(k - d)
    # とするかabs(k + d)とするか」を考えることと同値である。
    # dp[i][j][k] : マス (i, j) までの経路の偏りが k になることがあるか？
    max_k = 160 * 80
    dp = [[[False] * (max_k + 1) for _ in range(W + 1)] for _ in range(H + 1)]

    dp[0][1][0] = True
    dp[1][0][0] = True

    for i in range(H):
        for j in range(W):
            for k in range(max_k + 1):
                d = abs(A[i][j] - B[i][j])
                # i+1移動
                if k + d <= max_k:
                    dp[i + 1][j + 1][k + d] |= dp[i + 1][j][k]
                if abs(k - d) <= max_k:
                    dp[i + 1][j + 1][abs(k - d)] |= dp[i + 1][j][k]
                # j+1移動
                if k + d <= max_k:
                    dp[i + 1][j + 1][k + d] |= dp[i][j + 1][k]
                if abs(k - d) <= max_k:
                    dp[i + 1][j + 1][abs(k - d)] |= dp[i][j + 1][k]

    for k in range(max_k + 1):
        if dp[H][W][k]:
            return print(k)


if __name__ == "__main__":
    resolve()


# Optimized solution

def resolve():
    # (O):80（縦最大） × 80（横最大） × 80（各マスの最大の偏り）× 160（最大何回移動する必要があるか）
    H, W = list(map(int, input().split()))
    A = [tuple(map(int, input().split())) for _ in range(H)]
    B = [tuple(map(int, input().split())) for _ in range(H)]
    Sub = [[0] * W for i in range(H)]
    for i in range(H):
        for j in range(W):
            Sub[i][j] = abs(A[i][j] - B[i][j])

    # 移動直前の偏りをkとし、移動先のマス(i, j)
    # についてd = abs(A[i][j] - B[i][j])とした際に、
    # 移動後の偏りを abs(k - d) とするか abs(k + d) とするか」を考えることと同値である。
    # dp[i][j][k] : マス (i, j) までの経路の偏りが k になることがあるか？

    # Bitset演算 (3次元TLE)
    max_k = 80 * (H + W)
    dp = [[0] * W for _ in range(H)]
    dp[0][0] = 1 << (max_k + Sub[0][0]) | 1 << (max_k - Sub[0][0])

    for i in range(H):
        for j in range(W):
            d = Sub[i][j]
            if i:
                dp[i][j] |= dp[i - 1][j] << d | dp[i - 1][j] >> d
            if j:
                dp[i][j] |= dp[i][j - 1] << d | dp[i][j - 1] >> d

    ans = 10 ** 18
    for i in range(max_k * 2 + 1):
        if dp[H - 1][W - 1] & (1 << i):
            ans = min(ans, abs(max_k - i))
    print(ans)


if __name__ == "__main__":
    resolve()
# Original solution
#!usr/bin/env python3
from collections import defaultdict,deque
from heapq import heappush, heappop
import sys
import math
import bisect
import random
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS():return [list(x) for x in sys.stdin.readline().split()]
def S():
    res = list(sys.stdin.readline())
    if res[-1] == "\n":
        return res[:-1]
    return res
def IR(n):
    return [I() for i in range(n)]
def LIR(n):
    return [LI() for i in range(n)]
def SR(n):
    return [S() for i in range(n)]
def LSR(n):
    return [LS() for i in range(n)]

sys.setrecursionlimit(1000000)
mod = 1000000007

def solve():
    h,w = LI()
    a = LIR(h)
    b = LIR(h)
    for i in range(h):
        for j in range(w):
            a[i][j] -= b[i][j]
            if a[i][j] < 0:
                a[i][j] *= -1
    d = [(0,1),(1,0)]
    f = [0 for x in range(w)]
    M = (1<<25600)-1
    b = 12800
    f[0] = (1<<(b+a[0][0]))|(1<<(b-a[0][0]))
    for y in range(h):
        ny = y+1
        nf = [0 for x in range(w)]
        for x in range(w):
            nx = x+1
            if nx < w:
                f[nx] |= ((f[x]<<a[y][nx])|(f[x]>>a[y][nx]))
            if ny < h:
                nf[x] |= ((f[x]<<a[ny][x])|(f[x]>>a[ny][x]))
        if ny < h:
            f = [i for i in nf]
    ans = bin(f[w-1])[2:]
    ans = [abs(i-b) for i in range(len(ans)) if ans[len(ans)-i-1] == "1"]
    print((min(ans)))
    return

#Solve
if __name__ == "__main__":
    solve()


# Optimized solution
#!usr/bin/env python3
from collections import defaultdict,deque
from heapq import heappush, heappop
import sys
import math
import bisect
import random
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS():return [list(x) for x in sys.stdin.readline().split()]
def S():
    res = list(sys.stdin.readline())
    if res[-1] == "\n":
        return res[:-1]
    return res
def IR(n):
    return [I() for i in range(n)]
def LIR(n):
    return [LI() for i in range(n)]
def SR(n):
    return [S() for i in range(n)]
def LSR(n):
    return [LS() for i in range(n)]

sys.setrecursionlimit(1000000)
mod = 1000000007

def solve():
    h,w = LI()
    a = LIR(h)
    b = LIR(h)
    for i in range(h):
        for j in range(w):
            a[i][j] -= b[i][j]
            if a[i][j] < 0:
                a[i][j] *= -1
    d = [(0,1),(1,0)]
    f = [0 for x in range(w)]
    M = (1<<25600)-1
    b = 12800
    f[0] = (1<<(b+a[0][0]))|(1<<(b-a[0][0]))
    for y in range(h):
        ny = y+1
        nf = [0 for x in range(w)]
        for x in range(w):
            nx = x+1
            if nx < w:
                f[nx] |= ((f[x]<<a[y][nx])|(f[x]>>a[y][nx]))
                f[nx] &= M
            if ny < h:
                nf[x] |= ((f[x]<<a[ny][x])|(f[x]>>a[ny][x]))
                nf[x] &= M
        if ny < h:
            f = [i for i in nf]
    ans = bin(f[w-1])[2:]
    ans = [abs(i-b) for i in range(len(ans)) if ans[len(ans)-i-1] == "1"]
    print((min(ans)))
    return

#Solve
if __name__ == "__main__":
    solve()
# Original solution
#!/bin/bash
''':'
docker run --rm -it -v $(cd $(dirname $0) && pwd):/vo:ro pypy:3-2.4.0 /bin/bash -c "pypy3 /vo/$(basename $0) < /vo/g.inp"; exit $?
exit 0
'''
import sys

def _i(): return int(sys.stdin.readline().strip())
def _ia(): return [ int(x) for x in sys.stdin.readline().strip().split() ]

# read input
h,w = _ia()
ab = []
for _ in range(h): ab.append(_ia())
for i in range(h):
    r = ab[i]
    for j,bj in enumerate(_ia()):
        r[j] = abs(r[j] - bj)
    t = max(r)

# initialize
dp = [[None for _ in range(w)] for _ in range(h)]
dp[0][0] = {ab[0][0]}
for ij in range(1,h+w-1):
    for i in range(min(ij+1,h)):
        j = ij - i
        if j>=w: continue
        #
        x = ab[i][j]
        nxt = dp[i][j] = set()
        if i==0: ref= dp[i][j-1]
        elif j==0: ref = dp[i-1][j]
        else: ref = dp[i][j-1] | dp[i-1][j]
        #
        im = 0
        for idx in ref: nxt|= {abs(idx-x),idx+x}
            
# stdout
ref=dp[h-1][w-1]
print((min(ref)))


# Optimized solution
#!/bin/bash
''':'
docker run --rm -it -v $(cd $(dirname $0) && pwd):/vo:ro pypy:3-2.4.0 /bin/bash -c "pypy3 /vo/$(basename $0) < /vo/g.inp"; exit $?
exit 0
'''
import sys

def _ia(): return [ int(x) for x in sys.stdin.readline().strip().split() ]

# read input
h,w = _ia()
ab = []
for _ in range(h): ab.append(_ia())
for i in range(h):
    r = ab[i]
    for j,bj in enumerate(_ia()):
        r[j] = abs(r[j] - bj)
    t = max(r)

# initialize
dp = [[None for _ in range(w)] for _ in range(h)]
dp[0][0] = {ab[0][0]}
hw1 = h + w - 1
for ij in range(1,hw1):
    iend = ( hw1 - ij ) * 80
    for i in range(min(ij+1,h)):
        j = ij - i
        if j>=w: continue
        #
        ref = set()
        if i>0: ref|= dp[i-1][j]
        if j>0: ref|= dp[i][j-1]
        #
        x = ab[i][j]
        nxt = dp[i][j] = set()
        for idx in ref:
            ix = abs(idx-x)
            if ix<=iend: nxt.add(ix)
            ix = idx + x
            if ix<=iend: nxt.add(ix)
            
# stdout
print((min(dp[h-1][w-1])))
# Original solution
h, w = list(map(int,input().split()))
a = [list(map(int,input().split())) for i in range(h)]
b = [list(map(int,input().split())) for i in range(h)]

ab = [[0]*w for i in range(h)]
for ch in range(h):
    for cw in range(w):
        ab[ch][cw] = abs(a[ch][cw] - b[ch][cw])

ab0 = ab[0][0]
size = 80*(h+w)
dp = [[0]*w for hh in range(h)]
dp[0][0] |= 2**(size + ab0)
dp[0][0] |= 2**(size - ab0)
for ch in range(h):
    for cw in range(w):
        if ch < h-1:
            dp[ch+1][cw] |= dp[ch][cw] << ab[ch+1][cw]
            dp[ch+1][cw] |= dp[ch][cw] >> ab[ch+1][cw]
        if cw < w-1:
            dp[ch][cw+1] |= dp[ch][cw] << ab[ch][cw+1]
            dp[ch][cw+1] |= dp[ch][cw] >> ab[ch][cw+1]

a = dp[h-1][w-1]>>size
m = a&(-a)
print((m.bit_length()-1))

# Optimized solution
import sys
read = sys.stdin.buffer.read
input = sys.stdin.buffer.readline

h, w = list(map(int,input().split()))
a = [list(map(int,input().split())) for i in range(h)]
b = [list(map(int,input().split())) for i in range(h)]

ab = [[0]*w for i in range(h)]
for ch in range(h):
    for cw in range(w):
        ab[ch][cw] = abs(a[ch][cw] - b[ch][cw])

ab0 = ab[0][0]
size = 80*(h+w)
dp = [[0]*w for hh in range(h)]
dp[0][0] |= 2**(size + ab0)
dp[0][0] |= 2**(size - ab0)
for ch in range(h):
    for cw in range(w):
        if ch < h-1:
            dp[ch+1][cw] |= dp[ch][cw] << ab[ch+1][cw]
            dp[ch+1][cw] |= dp[ch][cw] >> ab[ch+1][cw]
        if cw < w-1:
            dp[ch][cw+1] |= dp[ch][cw] << ab[ch][cw+1]
            dp[ch][cw+1] |= dp[ch][cw] >> ab[ch][cw+1]

a = dp[h-1][w-1]>>size
m = a&(-a)
print((m.bit_length()-1))
# Original solution
h,w=list(map(int,input().split()))
a=[list(map(int,input().split()))for i in range(h)]
b=[list(map(int,input().split()))for i in range(h)]
c=[[abs(a[i][j]-b[i][j])for j in range(w)]for i in range(h)]
d=[[set()for i in range(w+1)]for j in range(h+1)]
d[1][1]=set([-c[0][0],c[0][0]])
for x in range(1,h+1):
    for y in range(1,w+1):
        if not (x==1 and y==1):
            a=d[x-1][y]|d[x][y-1]
            for i in a:
                d[x][y].add(i-c[x-1][y-1])
                if i+c[x-1][y-1]<=80:
                    d[x][y].add(i+c[x-1][y-1])
print((abs(min(d[h][w],key=abs))))

# Optimized solution
h,w=list(map(int,input().split()))
a=[list(map(int,input().split()))for i in range(h)]
b=[list(map(int,input().split()))for i in range(h)]
s=[0]*w
s[0]=p=1<<6400
for i in range(h):
    for j in range(w):
        d=abs(a[i][j]-b[i][j])
        if j>0:
            s[j]|=s[j-1]
        s[j]=(s[j]<<d)|(s[j]>>d)
t=s[-1]
for i in range(6401):
    if t&(p<<i) or t&(p>>i):
        print(i)
        break
# Original solution
# -*- coding: utf-8 -*-
import sys
from collections import deque
H,W=list(map(int, sys.stdin.readline().split()))

A=[ list(map(int, sys.stdin.readline().split())) for _ in range(H) ]
B=[ list(map(int, sys.stdin.readline().split())) for _ in range(H) ]

for h in range(H):
    for w in range(W):
        A[h][w]=abs(A[h][w]-B[h][w])

dp=[ [ 0 for _ in range(W) ] for __ in range(H) ]

Center=80*80      #中心地のセット マイナスの値もセットできるようにbitsetのゼロを80*80+1桁目に置く

#初期化
r,c=0,0
val=A[r][c]
dp[r][c]=1<<val+Center

q=deque()
q.append((0,0))
D=[(1,0),(0,1)]
Visit={}    #訪問済みの頂点にフラグ1を立てる
Visit[(0,0)]=1

while q:
    r,c=q.popleft()
    for dr,dc in D:
        if r+dr<H and c+dc<W:
            next_r=r+dr
            next_c=c+dc
            next_val=A[next_r][next_c]
            dp[next_r][next_c]|=dp[r][c]<<next_val
            dp[next_r][next_c]|=dp[r][c]>>next_val
            Visit[(next_r,next_c)]=1    #次の頂点をキューに入れたら、訪問済みに印をつける
            q.append((next_r,next_c))

ans=float("inf")
for i in range(80*80*2):
    bit=dp[H-1][W-1]>>i&1
    if bit==1:
        ans=min(ans,abs(i-Center))

print(ans)


# Optimized solution
# -*- coding: utf-8 -*-
import sys
from collections import deque,defaultdict

H,W=list(map(int, sys.stdin.readline().split()))
A=[ list(map(int, sys.stdin.readline().split())) for _ in range(H) ]
B=[ list(map(int, sys.stdin.readline().split())) for _ in range(H) ]

for h in range(H):
    for w in range(W):
        A[h][w]=abs(A[h][w]-B[h][w])

dp=[ [ 0 for _ in range(W) ] for __ in range(H) ]

Center=80*80      #中心地のセット マイナスの値もセットできるようにbitsetのゼロを80*80+1桁目に置く

#初期化
r,c=0,0
val=A[r][c]
dp[r][c]=1<<val+Center

q=deque()
q.append((0,0))
D=[(1,0),(0,1)]
Visit=defaultdict(lambda: 0)     #訪問済みの頂点にフラグ1を立てる
Visit[(0,0)]=1
D=[(1,0),(0,1)]

for r in range(H):
    for c in range(W):
        for dr,dc in D: #横に1つ移動か、下に1つ移動
            if r+dr<H and c+dc<W:   #移動しようとするマスが存在するならばif文内の処理を行う
                next_r=r+dr
                next_c=c+dc
                next_val=A[next_r][next_c]
                dp[next_r][next_c]|=dp[r][c]<<next_val  #次のマスの値が+の場合は、bitshift全体を左にシフト
                dp[next_r][next_c]|=dp[r][c]>>next_val  #次のマスの値が-の場合は、bitshift全体を右にシフト
                q.append((next_r,next_c))

ans=float("inf")
for i in range(Center*2):
    bit=dp[H-1][W-1]>>i&1
    if bit==1:
        ans=min(ans,abs(i-Center))

print(ans)
# Original solution
# -*- coding: utf-8 -*-
import sys

H,W=list(map(int, sys.stdin.readline().split()))
A=[ list(map(int, sys.stdin.readline().split())) for _ in range(H) ]
B=[ list(map(int, sys.stdin.readline().split())) for _ in range(H) ]

for h in range(H):
    for w in range(W):
        A[h][w]=abs(A[h][w]-B[h][w])

dp=[ [ 0 for _ in range(W) ] for __ in range(H) ]

Center=80*80      #中心地のセット マイナスの値もセットできるようにbitsetのゼロを80*80+1桁目に置く

#初期化
r,c=0,0
val=A[r][c]
dp[r][c]=1<<val+Center

D=[(1,0),(0,1)]

for r in range(H):
    for c in range(W):
        for dr,dc in D: #下に1つ移動したマス、右に1つ移動したマス
            if r+dr<H and c+dc<W:   #下のマスor右のマスが存在するならばif文内の処理を行う
                next_r=r+dr
                next_c=c+dc
                next_val=A[next_r][next_c]
                dp[next_r][next_c]|=dp[r][c]<<next_val  #次のマスの値が+の場合は、bitshift全体を左にシフト
                dp[next_r][next_c]|=dp[r][c]>>next_val  #次のマスの値が-の場合は、bitshift全体を右にシフト

ans=float("inf")
for i in range(Center*2):
    bit=dp[H-1][W-1]>>i&1
    if bit==1:
        ans=min(ans,abs(i-Center))

print(ans)


# Optimized solution
# -*- coding: utf-8 -*-
import sys

H,W=list(map(int, sys.stdin.readline().split()))
A=[ list(map(int, sys.stdin.readline().split())) for _ in range(H) ]
B=[ list(map(int, sys.stdin.readline().split())) for _ in range(H) ]

for h in range(H):
    for w in range(W):
        A[h][w]=abs(A[h][w]-B[h][w])

dp=[ [ 0 for _ in range(W) ] for __ in range(H) ]

Center=80*80      #中心地のセット マイナスの値もセットできるようにbitsetのゼロを80*80+1桁目に置く

#初期化
r,c=0,0
val=A[r][c]
dp[r][c]=1<<val+Center

D=[(1,0),(0,1)]

for r in range(H):
    for c in range(W):
        for dr,dc in D: #下に1つ移動したマス、右に1つ移動したマス
            if r+dr<H and c+dc<W:   #下のマス or 右のマスが存在するならばif文内の処理を行う
                next_r=r+dr
                next_c=c+dc
                next_val=A[next_r][next_c]
                dp[next_r][next_c]|=dp[r][c]<<next_val  #次のマスの値が+の場合は、bitshift全体を左にシフト
                dp[next_r][next_c]|=dp[r][c]>>next_val  #次のマスの値が-の場合は、bitshift全体を右にシフト

ans=float("inf")
for i in range(Center*2):
    bit=dp[H-1][W-1]>>i&1
    if bit==1:
        ans=min(ans,abs(i-Center))

print(ans)
# Original solution
from collections import deque
from copy import copy

row, column = list(map(int, input().split()))
map1 = [list(map(int, input().split())) for _ in range(row)]
map2 = [list(map(int, input().split())) for _ in range(row)]
map_ = [[n1 - n2 for n1, n2 in zip(row1, row2)] for row1, row2 in zip(map1, map2)]

n = map_[0][0]
queue = deque([(0, 0, n), (0, 0, -n)])
ansque = deque()

def bfs(queue):
    while True:
        nextqueue = deque()
        while queue:
            posr, posc, n = queue.popleft()
            if (posr, posc) == (row - 1, column - 1):
                ansque.append(abs(n))
            for dr, dc in zip([1, 0], [0, 1]):
                nextr = posr + dr
                nextc = posc + dc
                if 0 <= nextr < row and 0 <= nextc < column:
                    nextn = map_[nextr][nextc]
                    nextqueue.append((nextr, nextc, n + nextn))
                    nextqueue.append((nextr, nextc, n - nextn))
        if nextqueue:
            queue = copy(nextqueue)
        else:
            return ansque

print((min(bfs(queue))))


# Optimized solution
R, C = list(map(int, input().split()))

A = [list(map(int, input().split())) for _ in range(R)]
B = [list(map(int, input().split())) for _ in range(R)]

dp = [0] * C
dp[0] = s = 1 << 6400

for row_a, row_b in zip(A, B):
    for i, (a, b) in enumerate(zip(row_a, row_b)):
        d = abs(a - b)
        if i > 0:
            dp[i] |= dp[i - 1]
        dp[i] = (dp[i] << d) | (dp[i] >> d)

g = dp[-1]
for i in range(6401):
    if g & (s << i) or g & (s >> i):
        print(i)
        quit()
# Original solution
import sys
input = sys.stdin.buffer.readline
from collections import deque

def main():
    H,W = list(map(int,input().split()))
    p = [[0 for _ in range(W)] for _ in range(H)]
    point = [[[] for _ in range(W)] for _ in range(H)]
    
    for i in range(H):
        a = list(map(int,input().split()))
        for j,num in enumerate(a):
            p[i][j] += num
    
    for i in range(H):
        b = list(map(int,input().split()))
        for j,num in enumerate(b):
            p[i][j] -= num

    point[0][0].append(p[0][0])
    q = deque([(0,0)])
    while q:
        x,y = q.popleft()
        dx,dy = [1,0],[0,1]
        for i in range(2):
            nx,ny = x+dx[i],y+dy[i]
            if (0<=nx<H and 0<=ny<W):
                for num in point[x][y]:
                    point[nx][ny].append(num+p[nx][ny])
                    point[nx][ny].append(num-p[nx][ny])
                point[nx][ny] = list(set(point[nx][ny]))
                q.append((nx,ny))
    
    point[-1][-1].sort(key=lambda x:abs(x))
    print((abs(point[-1][-1][0])))

if __name__ == "__main__":
    main()

# Optimized solution
import sys
input = sys.stdin.buffer.readline

def main():
    H,W = list(map(int,input().split()))
    point = [[0]*W for _ in range(H)]
    
    for i in range(H):
        a = list(map(int,input().split()))
        for j in range(W):
            point[i][j] += a[j]

    for i in range(H):
        b = list(map(int,input().split()))
        for j in range(W):
            point[i][j] = abs(point[i][j]-b[j])
    
    base = 3200
    dp = [[0]*W for _ in range(H)]
    dp[0][0] = (1 << (base+point[0][0])) | (1 << (base-point[0][0]))
    
    for i in range(H):
        for j in range(W):
            if j < W-1:
                dp[i][j+1] |= (dp[i][j] << point[i][j+1])
                dp[i][j+1] |= (dp[i][j] >> point[i][j+1])
            if i < H-1:
                dp[i+1][j] |= (dp[i][j] << point[i+1][j])
                dp[i+1][j] |= (dp[i][j] >> point[i+1][j])
    
    ans = dp[-1][-1] >> base
    for i in range(ans.bit_length()):
        if (ans >> i)&1:
            print(i)
            exit()
    
if __name__ == "__main__":
    main()
# Original solution
h,w = list(map(int,input().split()))
a = [list(map(int,input().split())) for i in range(h)]
b = [list(map(int,input().split())) for i in range(h)]
kanousei = [[[0] * (100 ** 3) for i in range(w)] for j in range(h)]
kanousei[0][0][abs(a[0][0]-b[0][0])] = 1
kanousei[0][0][abs(b[0][0]-a[0][0])] = 1
for RangeFromZero in range(1,h+w-1):
  #     print(RangeFromZero)
    for x in range(RangeFromZero,-1,-1):
        y = RangeFromZero-x
  #         print(x,y)
        if x < w and y < h:
            if 0 < x:
                for i in range(100 ** 2):
                    if kanousei[y][x-1][i] == 1:
                        kanousei[y][x][i+abs(a[y][x]-b[y][x])] = 1
                        kanousei[y][x][abs(i-abs(a[y][x]-b[y][x]))] = 1
            if 0 < y:
                for i in range(100 ** 2):
                    if kanousei[y-1][x][i] == 1:
                        kanousei[y][x][i+abs(a[y][x]-b[y][x])] = 1
                        kanousei[y][x][abs(i-abs(a[y][x]-b[y][x]))] = 1
print((kanousei[h-1][w-1].index(1)))

# Optimized solution
h,w = list(map(int,input().split()))
a = [list(map(int,input().split())) for i in range(h)]
b = [list(map(int,input().split())) for i in range(h)]
kanousei = [[[0] * (100 ** 2) for i in range(w)] for j in range(h)]
kanousei[0][0][abs(a[0][0]-b[0][0])] = 1
kanousei[0][0][abs(b[0][0]-a[0][0])] = 1
for RangeFromZero in range(1,h+w-1):
  #     print(RangeFromZero)
    for x in range(RangeFromZero,-1,-1):
        y = RangeFromZero-x
  #         print(x,y)
        if x < w and y < h:
            if 0 < x:
                for i in range(100 ** 2):
                    if kanousei[y][x-1][i] == 1:
                        kanousei[y][x][i+abs(a[y][x]-b[y][x])] = 1
                        kanousei[y][x][abs(i-abs(a[y][x]-b[y][x]))] = 1
            if 0 < y:
                for i in range(100 ** 2):
                    if kanousei[y-1][x][i] == 1:
                        kanousei[y][x][i+abs(a[y][x]-b[y][x])] = 1
                        kanousei[y][x][abs(i-abs(a[y][x]-b[y][x]))] = 1
print((kanousei[h-1][w-1].index(1)))
# Original solution
import sys
input = sys.stdin.buffer.readline

h, w = list(map(int, input().split()))
grid = [None for _ in range(h)]
poss = [[set() for x in range(w)] for y in range(h)]
tmp = [list(map(int, input().split())) for _ in range(h * 2)]
for i, (l1, l2) in enumerate(zip(tmp, tmp[h:])):
	grid[i] = [abs(x - y) for x, y in zip(l1, l2)]
poss[0][0].add(-grid[0][0])
poss[0][0].add(grid[0][0])
for i in range(h):
	for j in range(w - 1):
		for c in poss[i][j]:
			m = grid[i][j + 1]
			poss[i][j + 1].add(c - m)
			poss[i][j + 1].add(c + m)
	if i == h - 1:
		break
	for j in range(w):
		for c in poss[i][j]:
			m = grid[i + 1][j]
			poss[i + 1][j].add(c - m)
			poss[i + 1][j].add(c + m)
print((min(abs(x) for x in poss[-1][-1])))

# Optimized solution
import sys
input = sys.stdin.buffer.readline

h, w = list(map(int, input().split()))
a = [list(map(int, input().split())) for _ in range(h)]
b = [list(map(int, input().split())) for _ in range(h)]
g = [list(abs(x - y) for x, y in zip(l1, l2)) for l1, l2 in zip(a, b)]
poss = [[0] * w for _ in range(h)]
poss[0][0] |= 1 << 6400 + g[0][0]
poss[0][0] |= 1 << 6400 - g[0][0]
for i in range(h):
	for j in range(w - 1):
		poss[i][j + 1] |= poss[i][j] << g[i][j + 1]
		poss[i][j + 1] |= poss[i][j] >> g[i][j + 1]
	if i != h - 1:
		for j in range(w):
			poss[i + 1][j] |= poss[i][j] << g[i + 1][j]
			poss[i + 1][j] |= poss[i][j] >> g[i + 1][j]
res = poss[-1][-1]
for i in range(6400):
	if res & (1 << 6400 + i) or res & (1 << 6400 - i):
		print(i)
		exit()
# Original solution
import sys
input = sys.stdin.buffer.readline

h, w = list(map(int, input().split()))
a = [list(map(int, input().split())) for _ in range(h)]
b = [list(map(int, input().split())) for _ in range(h)]
g = [list(abs(x - y) for x, y in zip(l1, l2)) for l1, l2 in zip(a, b)]
poss = [[0] * w for _ in range(h)]
poss[0][0] |= 1 << 6400 + g[0][0]
poss[0][0] |= 1 << 6400 - g[0][0]
for i in range(h):
	for j in range(w - 1):
		poss[i][j + 1] |= poss[i][j] << g[i][j + 1]
		poss[i][j + 1] |= poss[i][j] >> g[i][j + 1]
	if i != h - 1:
		for j in range(w):
			poss[i + 1][j] |= poss[i][j] << g[i + 1][j]
			poss[i + 1][j] |= poss[i][j] >> g[i + 1][j]
res = poss[-1][-1]
for i in range(6400):
	if res & (1 << 6400 + i) or res & (1 << 6400 - i):
		print(i)
		exit()


# Optimized solution
import sys
input = sys.stdin.readline

def main():
	h, w = list(map(int, input().split()))
	a = [list(map(int, input().split())) for _ in range(h)]
	b = [list(map(int, input().split())) for _ in range(h)]
	g = [list(abs(x - y) for x, y in zip(l1, l2)) for l1, l2 in zip(a, b)]
	poss = [0] * w
	poss[0] |= 1 << 6400 + g[0][0]
	poss[0] |= 1 << 6400 - g[0][0]
	for i in range(h):
		for j in range(w):
			if j < w - 1:
				d = g[i][j + 1]
				poss[j + 1] |= poss[j] << d
				poss[j + 1] |= poss[j] >> d
			if i < h - 1:
				d = g[i + 1][j]
				poss[j] = poss[j] << d | poss[j] >> d
	res = poss[-1]
	for i in range(6400):
		if res & (1 << 6400 + i) or res & (1 << 6400 - i):
			print(i)
			exit()

if __name__ == "__main__":
	main()