#include	<bits/stdc++.h>
using	namespace	std;
typedef	long long ll;

// int/long:		-2,147,483,648 - 2,147,483,647 (-2^31 <= int < 2^31)
// long/long long:	-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807 (-2^63 <= long < 2^63)

// lower_bound(A.begin(), A.end(), N)
// upper_bound(...

// A.erase(unique(A.begin(), A.end()), A.end())

// bit: &/and, |/or, ^/xor, ~/not

// getline(cin, String)
// while (getline(cin, S)) {}

// #include <cstdio>
// int a;
// scanf("%d", &a);
// printf("%d\n", a);
//
// for (int i=0; i<n; ++i)
// 	scanf("%d", &a[i]);
//
// char c;
// scanf(" %c", &c);
//
// cout << "\n";

// cout <<fixed <<setprecision(10)

// priority_queue<int> q;
// priority_queue<int, vector<int>, less<int>> q; // Default: vector, less
// priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> q;

// Graph
// Warshall-Floyd: Distance between each node, N^3
// Dijkstra: Distance from the start node, N^2
// DFS(Depth-First Search)

//
// Notes
//
// When specified less than N, try full scan.
// RE: empty vector
// Check Qs
// long/int
// xor -> count each bit
// Check values
// 	1,000,000 -> Loop
// 	100,000	-> vector(int:400KB, long:800KB) 

#define	INF (1<<30)
//1,073,741,824
//= 536,870,912 *2

#define	MOD 1000000007

/*
ll	myPow(ll x, ll n) {
	if (0==n)
		return 1;
	if (0==n%2)
		return myPow(x*x%MOD, n/2);
	else
		return x*myPow(x, n-1)%MOD;
}
*/
ll	myPow(ll x, ll n) {
	ll r=1;
	while(n>0)
		if (0==n%2) {
			x *=x;
			x %=MOD;
			n /=2;
		} else {
			r *=x;
			r %=MOD;
			n--;
		}
	return r;
}

#define	Rep0(i, n)	for (int i=0; i<n; i++)
#define	Rep1(i, n)	for (int i=1; i<=n; i++)
#define Sort(P)	sort(P.begin(), P.end())
#define Rev(P)	reverse(P.begin(), P.end())

int	Count(const int x0, const int y0, const int x1, const int y1, const vector<vector<int>> &SUM) {
	return SUM.at(x1).at(y1)+SUM.at(x0).at(y0)-SUM.at(x1).at(y0)-SUM.at(x0).at(y1);
}

int	main() {
	int H, W, K;
	cin >>H >>W >>K;
	vector<vector<int>> S(H+1, vector<int> (W+1, 0));
	Rep1(i, H) {
		string SS;
		cin >>SS;
		Rep1(j, W)
			S.at(i).at(j)=SS.at(j-1)-'0';
	}
	// Input Done
	// cumulative sum table
	vector<vector<int>> CUSUM(H+1, vector<int> (W+2, 0));
	Rep1(i, H) {
		int s=0;
		Rep1(j, W) {
			s +=S.at(i).at(j);
			CUSUM.at(i).at(j)=CUSUM.at(i-1).at(j)+s;
		}
		CUSUM.at(i).at(W+1)=INF;
	}
	int SS=H+W;
	int M=pow(2, H-1);
	Rep0(i, M) { // For each combination of holizontal lines
		vector<int> h;
		h.push_back(0);
		int SSS=0; // Num of lines
		int I=i;
		int J=1;
		while(I>0) {
			if (1==I%2) {
				h.push_back(J);
				SSS++;
			}
			I/=2;
			J++;
		}
		h.push_back(H);
		// Count vertical lines
		int LL=0;
		int RR=W+1;
		bool FAIL=false;
		while(LL<W) { // Count vertical lines
			int RRR=W;
			Rep1(j, h.size()-1) {
				int h0=h.at(j-1);
				int h1=h.at(j);
				int L=LL;
				int R=RR;
				while (R-L>1) {
					int M=(L+R)/2;
					if (Count(h0, LL, h1, M, CUSUM)>K)
						R=M;
					else
						L=M;
				}
				if (L==LL) { // Not possible
					FAIL=true;
					break;
				}
				RRR=min(RRR, L);
			}
			if (FAIL)
				break;
			if (RRR<W) // Add vertical line after L
				SSS++;
			LL=RRR;
		}
		if (FAIL)
			continue;
		SS=min(SS, SSS);
	}
	cout <<SS <<endl;
	return 0;
}



Measured memory_bytes: 384