unittest
{
	assert( [ "3 5 4", "11100", "10001", "00111" ].solve == 2 );
	assert( [ "3 5 8", "11100", "10001", "00111" ].solve == 0 );
	assert( [ "4 10 4", "1110010010", "1000101110", "0011101001", "1101000111" ].solve == 3 );
}



import std.algorithm;
import std.conv;
import std.format;
import std.range;
import std.stdio;

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

auto solve( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto h = 0L;
	auto w = 0L;
	auto k = 0L;
	input.front.formattedRead!"%s %s %s"( h, w, k );
	auto sss = new dchar[][]( h, w );
	foreach( ref ss; sss )
	{
		input.popFront;
		ss = input.front.to!( dchar[] );
	}
	
	// 横に割るところをbit全列挙
	auto ans = long.max;
	LOOP: foreach( b; 0L .. 1L << ( h - 1 ) )
	{
		// 横に割るところを境にしてy座標ごとにグルーピング
		auto n = 0L;
		auto ps = new long[ h ];
		foreach( y, ref p; ps )
		{
			p = n;
			if( b & ( 1L << y ) ) n++;
		}
		
		// 縦に割るところを貪欲法で判定
		auto d = n;
		auto ts = new long[ n + 1 ];
		foreach( x; 0L .. w )
		{
			auto dd = false;
			auto cs = new long[ n + 1 ];
			foreach( y, p; ps )
			{
				if( sss[ y ][ x ] == '1' )
				{
					cs[ p ]++;
					if( k < cs[ p ] ) continue LOOP;			// 一列でkを超えるので無理
					if( k < cs[ p ] + ts[ p ] ) dd = true;		// kを超えるのでこの列の手前で割る
				}
			}
			d += dd;
			if( dd ) ts[]  = cs[];
			else     ts[] += cs[];
		}
		ans = min( ans, d );
	}
	return ans;
}
