unittest
{
	assert( [ "3 3", ".##", ".#.", "##." ].parse.expand.solve == 1 );
	assert( [ "2 2", "#.", ".#" ].parse.expand.solve == 2 );
	assert( [ "4 4", "..##", "#...", "###.", "###." ].parse.expand.solve == 0 );
	assert( [ "5 5", ".#.#.", "#.#.#", ".#.#.", "#.#.#", ".#.#." ].parse.expand.solve == 4 );
}



import std.algorithm;
import std.conv;
import std.functional;
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 css = new dchar[][]( hw[ 0 ], hw[ 1 ] );
	foreach( ref cs; css )
	{
		input.popFront;
		cs = input.front.to!( dchar[] );
	}
	return tuple( css );
}

auto solve( dchar[][] css )
{
	return ( css[ 0 ][ 0 ] == '#' ) + solve2( css, 0, 0 );
}

long solve2( dchar[][] css, long sy, long sx )
{
	if( sy + 1 == css.length && sx + 1 == css[ 0 ].length ) return 0;
	
	auto t = long.max;
	auto dy = 0L;
	foreach( y; sy + 1 .. css.length.signed )
	{
		if( css[ y - 1 ][ sx ] == '.' && css[ y ][ sx ] == '#' ) dy++;
		t = min( t, dy + memoize!solve2( css, y, sx ) );
	}
	auto dx = 0L;
	foreach( x; sx + 1 .. css[ sy ].length.signed )
	{
		if( css[ sy ][ x - 1 ] == '.' && css[ sy ][ x ] == '#' ) dx++;
		t = min( t, dx + memoize!solve2( css, sy, x ) );
	}
	return t;
}
