unittest
{
	assert( [ "2 2", "1 2", "3 4", "3 4", "2 1" ].parse.expand.solve == 0 );
	assert( [ "2 3", "1 10 80", "80 10 1", "1 2 3", "4 5 6" ].parse.expand.solve == 2 );
	
	assert( [ "2 2", "0 0", "0 0", "80 80", "80 80" ].parse.expand.solve == 80 );		// 追加ケース
}



import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto hw = input.front.split.to!( long[] );
	auto ass = new long[][]( hw[ 0 ], hw[ 1 ] );
	foreach( ref as; ass )
	{
		input.popFront;
		as = input.front.split.to!( long[] );
	}
	auto bss = new long[][]( hw[ 0 ], hw[ 1 ] );
	foreach( ref bs; bss )
	{
		input.popFront;
		bs = input.front.split.to!( long[] );
	}
	return tuple( ass, bss );
}

auto solve( long[][] ass, long[][] bss )
{
	// dp[ y ][ x ][ 偏り ] = この位置でこの偏りにできるか
	auto dp = new bool[][][]( ass.length, ass[ 0 ].length, 1 + ( ass.length + ass[ 0 ].length - 1 ) * 80 );
	dp[ 0 ][ 0 ][ abs( ass[ 0 ][ 0 ] - bss[ 0 ][ 0 ] ) ] = true;
	for( auto y = 0L; y < dp.length; y++ )
	{
		for( auto x = 0L; x < dp[ y ].length; x++ )
		{
			for( auto d = 0L; d < dp[ y ][ x ].length; d++ )
			{
				if( !dp[ y ][ x ][ d ] ) continue;
				
				if( y + 1 < dp.length )
				{
					auto v = abs( ass[ y + 1 ][ x ] - bss[ y + 1 ][ x ] );
					dp[ y + 1 ][ x ][ abs( d - v ) ] = true;
					dp[ y + 1 ][ x ][      d + v   ] = true;
				}
				if( x + 1 < dp[ y ].length )
				{
					auto v = abs( ass[ y ][ x + 1 ] - bss[ y ][ x + 1 ] );
					dp[ y ][ x + 1 ][ abs( d - v ) ] = true;
					dp[ y ][ x + 1 ][      d + v   ] = true;
				}
			}
		}
	}
	foreach( d, b; dp[ $ - 1 ][ $ - 1 ] )
	{
		if( b ) return d;
	}
	assert( false );
}
