#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <vector>
#include <string.h>
#include <string>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <math.h>
#include <algorithm>
#include <numeric>

using namespace std;

// マクロ&定数 ============================================================
typedef unsigned int uint;
typedef long long ll;
//typedef pair<int, int> P;

typedef vector<int> vint;
typedef vector<ll> vll;
typedef vector<double> vdouble;
typedef vector<bool> vbool;
typedef vector<string> vstring;
typedef vector<char> vchar;

typedef vector<pair<int, int>> vpint;
typedef vector<pair<ll, ll>> vpll;
typedef vector<pair<double, double>> vpdouble;

typedef vector<vector<int>> vvint;
typedef vector<vector<ll>> vvll;
typedef vector<vector<double>> vvdouble;
typedef vector<vector<bool>> vvbool;

typedef vector<vector<string>> vvstring;

const int c_YET = -1;
const int INF = 1e9 + 1;
const ll LLINF = 1e17 + 1;
const int DX[9] = { 0,0,1,-1, 1, 1, -1, -1, 0 }; // 4;４近傍
const int DY[9] = { 1,-1,0,0, 1, -1, 1, -1, 0 }; // 8:８近傍 9:(0,0)を含む
const ll MOD = 1e9 + 7; //10^9 + 7
const ll MAX = 1e9;
const double PI = 3.14159265358979323846264338327950288;
//========================================================================




int main() {

	//==================================
	cin.tie(nullptr);
	ios_base::sync_with_stdio(false);
	cout << fixed << setprecision(30);
	//==================================



	int H, W, K;
	cin >> H >> W >> K;

	vstring S(H);
	for (int i = 0; i < H; i++)
	{
		cin >> S[i];
	}




	int ans = INF;
	for (int bit = 0; bit < (1 << H); bit++) // 横線の位置を全探索 3=>[3の手前に線を入れる]   << O(2^H) >> 
	{
		// わかりにくいからリストにする
		vint lines;
		lines.emplace_back(0); // begin
		for (int i = 0; i < H; i++)  //    << O(H) >> 
		{
			if((bit >> i) & 1)
			{
				lines.emplace_back(i+1); // 線を手前に入れるから値は１大きく。
			}
		}
		lines.emplace_back(H); // end

		// 横線で区切って縦方向に集計
		vvint renewed(lines.size()- 1); 
		for (int i = 0; i < lines.size()-1; i++) //    << O(HW) >>
		{
			for (int w = 0; w < W; w++)
			{
				int white = 0;
				for (int h = lines[i]; h < lines[i + 1]; h++)
				{
					if (S[h][w] == '1')
					{
						white++;
					}
				}
				renewed[i].emplace_back(white);
			}

		}


		// 縦線を入れる。
		vint tate = {0};
		int new_H = renewed.size();
		int begin_w = 0;
		int end_w = W;
		
		vvint ruiseki(new_H);         //    << O(HW) >>
		for (int h = 0; h < new_H; h++)
		{
			ruiseki[h].emplace_back(renewed[h][0]);
			for (int w = 1; w < W; w++)
			{
				ruiseki[h].emplace_back(ruiseki[h][w - 1] + renewed[h][w]);
			}
		}


		bool flg = true;
		while (flg)
		{
			if (tate.size() == 998)
			{
				int rg = 4;
			}


			bool found = false;
			for (int h = 0; h < new_H; h++)
			{
				// にぶたん   //    << O(logW) >>
				if (begin_w == 0)
				{
					auto Iter = upper_bound(ruiseki[h].begin() + begin_w, ruiseki[h].begin() + end_w, K);				
					int idx = Iter - ruiseki[h].begin();

					if (idx == begin_w)
					{
						flg = false;
						break;
					}

					if (idx < W)
					{
						found = true;
						end_w = idx;
					}
				}
				else
				{
					auto Iter = upper_bound(ruiseki[h].begin() + begin_w, ruiseki[h].begin() + end_w, K + ruiseki[h][begin_w - 1]);
					int idx = Iter - ruiseki[h].begin();

					if (idx < W)
					{
						found = true;
						end_w = idx;
					}
					if (idx == begin_w)
					{
						flg = false;
						break;
					}
				}


				//int white = 0;
				//for (int w = begin_w; w < end_w; w++)
				//{
				//	white += renewed[h][w];

				//	if (white > K)
				//	{
				//		found = true;
				//		end_w = w; // ループを止めてるから小さいほうで更新されるはず
				//	}
				//}
			}

			tate.emplace_back(end_w);



			if (!found || end_w == W)
			{
				break;
			}

			begin_w = end_w;
			end_w = W;


		}


		// 縦線で区切って横方向にも集計
		vvint completed(tate.size() - 1);
		for (int i = 0; i < tate.size() - 1; i++)
		{
			for (int h = 0; h < new_H; h++)
			{
				int white = 0;
				for (int w = tate[i]; w < tate[i + 1]; w++)
				{
					white += renewed[h][w];
				}
				completed[i].emplace_back(white); // 90度回転してしまうけど最後だから気にしない。
			}

		}

		// 確認して答えを更新
		for (int i = 0; i < completed.size(); i++)
		{
			for (int j = 0; j < completed[0].size(); j++)
			{
				if (completed[i][j] > K)
				{
					// NG
					i = INF;
					j = INF;
				}
				else if (i == completed.size() - 1 && j == completed[0].size() - 1)
				{
					ans = min(ans, int(lines.size() + tate.size() - 4));
				}

			}

		}



	}



	cout << ans;

}



Measured memory_bytes: 512