#pragma region header
#include <iostream>
#include <iomanip>
#include <cmath>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
using namespace std;
typedef long long ll;
template <class T> ll size(const T& x) { return x.size(); }
#define rep(i,a,b) for(ll i = (a); i < (b); i++)
#define iter(it,c) for(auto it = (c).begin(); it != (c).end();++it)
#define pb push_back
#define fs first
#define sc second
#define MOD 1000000007;
typedef pair<ll, ll> ii;
typedef vector<ll> vi;
typedef vector<ii> vii;
template <class T> T smod(T a, T b) {
	return (a % b + b) % b;
}

const int INF = ~(1 << 31);
const double pi = acos(-1);
const double EPS = 1e-9;

#pragma endregion

struct PrefixSum2D {
public:
	PrefixSum2D(vector<vi> A, int t_h, int t_w)
	{
		arr = A;
		h = t_h + 1; w = t_w + 1;
		row = vector<vi >(h, vi(w));
		col = vector<vi >(h, vi(w));
		pre = vector<vi >(h, vi(w));
		vis = vector<vector<bool> >(h, vector<bool>(w));
		get_prefix();
	}
	PrefixSum2D() { };

	int qsum(int y1, int x1, int y2, int x2) {
		y1++; x1++; y2++; x2++;
		//cout << y1 << ' ' << x1 << ' ' << y2 << ' ' << x2 << endl;
		return pre[y2][x2] - pre[y1 - 1][x2] - pre[y2][x1 - 1] + pre[y1 - 1][x1 - 1];
	}

private:
	vector<vi > arr;
	vector<vi > row;
	vector<vi > col;
	vector<vi > pre;
	vector<vector<bool> > vis;
	int h, w;
	void fill_pre(int i, int j) {
		if (i == 0 || j == 0 || vis[i][j]) return;
		vis[i][j] = true;
		pre[i - 1][j] = pre[i][j] - row[i - 1][j - 1];
		pre[i][j - 1] = pre[i][j] - col[i - 1][j - 1];
		fill_pre(i - 1, j);
		fill_pre(i, j - 1);
	}

	void get_prefix() // HxW matrix, cnt = sum of arr
	{
		ll cnt = 0;
		rep(i, 0, h - 1)rep(j, 0, w - 1) {
			vis[i][j] = 0;
			pre[i][j] = 0;
			cnt += arr[i][j];
		}
		rep(i, 0, h - 1) {
			rep(x, 0, w - 1) {
				if (i == 0) {
					col[i][x] = arr[i][x];
				}
				else
				{
					col[i][x] = arr[i][x] + col[i - 1][x];
				}

				if (x == 0) {
					row[i][x] = arr[i][x];
				}
				else {
					row[i][x] = arr[i][x] + row[i][x - 1];
				}
			}
		}
		rep(i, 0, h - 1) {
			pre[i][0] = 0;
		}
		rep(i, 0, w - 1) {
			pre[0][i] = 0;
		}
		pre[1][1] = arr[0][0];
		pre[h - 1][w - 1] = cnt;
		fill_pre(h - 1, w - 1);
	}
};

ll h, w, k;
PrefixSum2D P;
vector<bool> Y;
ll mn = INF;

bool sqrsplit(int x1, int x2)
{
	vector<int> Ys;
	Ys.pb(0);
	rep(i, 0, h-1)
	{
		if (Y[i] == 1) Ys.pb(i+1);
	}
	Ys.pb(h);
	bool f = true;
	ll t = 0;
	rep(i, 1, Ys.size())
	{
		if (P.qsum(Ys[i - 1], x1, Ys[i]-1, x2) > k)
		{
			f = false;
		}
	}
	return f;
}


vi B;
ll solve() {
	int last = 0;
	ll cnt = 0;
	ll i = 0;
	B.clear();
	while(i < w)
	{
		if (!sqrsplit(last, i))
		{
			if (last == i) { return INF; }
			B.pb(i - 1);
			cnt++;
			last = i;
		}
		else i++;
	}
	//if (last == i && i == w - 1) if (!sqrsplit(w - 1, w - 1)) { return INF; }
	return cnt;
}

vector<bool> S;
vi X;

void bt(int at, int cnt)
{
	if (at == h-1)
	{
		if (cnt + solve() < mn)
		{
			S = Y;
			X = B;
		}
		mn = min(mn, cnt + solve());
		return;
	}
	rep(i, 0, 2)
	{
		Y[at] = i;
		bt(at + 1, cnt+(i==1));
	}
}

int main()
{
	cin >> h >> w >> k;
	Y = vector<bool>(h-1);
	vector< vi > A = vector<vi>(h, vi(w));
	rep(i, 0, h)
	{
		string in;
		cin >> in;
		rep(j, 0, in.size())
		{
			A[i][j] = in[j] - '0';
		}
	}
	P = PrefixSum2D(A, h, w);
	bt(0,0);
	rep(i, 0, S.size()) cerr << S[i] << ' '; cerr << endl;
	rep(i, 0, X.size()) cerr << X[i] << ' '; cerr << endl;
	cout << mn << endl;
}


Measured memory_bytes: 768