Problem:
Score : 500 points

Problem Statement

We have a chocolate bar partitioned into H horizontal rows and W vertical columns of squares.

The square (i, j) at the i-th row from the top and the j-th column from the left is dark if S_{i,j} is 0, and white if S_{i,j} is 1.

We will cut the bar some number of times to divide it into some number of blocks. In each cut, we cut the whole bar by a line running along some boundaries of squares from end to end of the bar.

How many times do we need to cut the bar so that every block after the cuts has K or less white squares?

Constraints

1 \leq H \leq 10

1 \leq W \leq 1000

1 \leq K \leq H \times W

S_{i,j} is 0 or 1.

Input

Input is given from Standard Input in the following format:

H W K
S_{1,1}S_{1,2}...S_{1,W}
:
S_{H,1}S_{H,2}...S_{H,W}

Output

Print the number of minimum times the bar needs to be cut so that every block after the cuts has K or less white squares.

Sample Input 1

3 5 4
11100
10001
00111

Sample Output 1

2

For example, cutting between the 1-st and 2-nd rows and between the 3-rd and 4-th columns - as shown in the figure to the left - works.

Note that we cannot cut the bar in the ways shown in the two figures to the right.

Sample Input 2

3 5 8
11100
10001
00111

Sample Output 2

0

No cut is needed.

Sample Input 3

4 10 4
1110010010
1000101110
0011101001
1101000111

Sample Output 3

3

Solution in C (GCC 5.4.1) (judge verdict: Accepted)

#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// 内部定数
#define D_SIZE_MAX		1005									// 最大サイズ

// 内部変数
static FILE *szpFpI;											// 入力
static int siW, siH;											// 幅・高さ
static char sc2Mass[D_SIZE_MAX][D_SIZE_MAX];					// マス
static int siWCnt;												// ホワイトチョコレート数

// 内部変数 - テスト用
#ifdef D_TEST
	static int siRes;
	static FILE *szpFpA;
	static int siTNo;
#endif

// １行出力
int
fOutLine(
	char *pcpLine				// <I> １行
)
{
	char lc1Buf[1024];

#ifdef D_TEST
	lc1Buf[0] = '\0';
	fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
	if (strcmp(lc1Buf, pcpLine)) {
		siRes = -1;
	}
#else
	printf("%s", pcpLine);
#endif

	return 0;
}

// ホワイトチョコレート数 - 取得
int
fGetWCnt(
	int piCol					// <I> 列
	, int *pipRLen				// <I> 行長さ
	, int piRCnt				// <I> 行長さ数
	, int *pipWCnt				// <O> ホワイトチョコレート数
)
{
	int i, j;

	int liRow = 0;
	for (i = 0; i < piRCnt; i++) {
		pipWCnt[i] = 0;
		for (j = 0; j < pipRLen[i]; j++) {
			if (sc2Mass[liRow][piCol] == '1') {
				pipWCnt[i]++;
				if (pipWCnt[i] > siWCnt) {
					return -1;
				}
			}
			liRow++;
		}
	}

	return 0;
}

// 横分割
int
fDivW(
	int *pipRLen				// <I> 行長さ
	, int piRCnt				// <I> 行長さ数
)
{
	int i, j, liRet;

	// １列目
	int li1WCnt[D_SIZE_MAX];
	liRet = fGetWCnt(0, pipRLen, piRCnt, li1WCnt);
	if (liRet != 0) {
		return INT_MAX;
	}

	// ２列目以降
	int liDCnt = piRCnt - 1;
	for (i = 1; i < siW; i++) {
		int li1WCnt2[D_SIZE_MAX];
		liRet = fGetWCnt(i, pipRLen, piRCnt, li1WCnt2);
		if (liRet != 0) {
			return INT_MAX;
		}

		// 結合
		for (j = 0; j < piRCnt; j++) {
			li1WCnt[j] += li1WCnt2[j];
			if (li1WCnt[j] > siWCnt) {
				break;
			}
		}
		if (j == piRCnt) {
			continue;
		}

		// 結合不可
		for (j = 0; j < piRCnt; j++) {
			li1WCnt[j] = li1WCnt2[j];
		}
		liDCnt++;
	}

	return liDCnt;
}

// 縦分割
int
fDivH(
	int piRow					// <I> 行
	, int *pipRLen				// <I> 行長さ
	, int piRCnt				// <I> 行長さ数
)
{
	// 終了
	if (piRow >= siH) {

		// 横分割
		return fDivW(pipRLen, piRCnt);
	}

	// 分割する
	pipRLen[piRCnt] = 1;
	int liCnt = fDivH(piRow + 1, pipRLen, piRCnt + 1);

	// 分割しない
	pipRLen[piRCnt - 1]++;
	int liCnt2 = fDivH(piRow + 1, pipRLen, piRCnt);
	if (liCnt > liCnt2) {
		liCnt = liCnt2;
	}

	return liCnt;
}

// 実行メイン
int
fMain(
)
{
	int i;
	char lc1Buf[1024];

	// 幅・高さ・ホワイトチョコレート数 - 取得
	fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
	sscanf(lc1Buf, "%d%d%d", &siH, &siW, &siWCnt);

	// マス - 取得
	for (i = 0; i < siH; i++) {
		fgets(sc2Mass[i], sizeof(sc2Mass[0]), szpFpI);
	}

	// 分割
	int li1RLen[D_SIZE_MAX];
	li1RLen[0] = 1;
	int liCnt = fDivH(1, li1RLen, 1);

	return liCnt;
}

// １回実行
int
fOne(
)
{
	int liRet;
	char lc1Buf[1024];

	// 入力 - セット
#ifdef D_TEST
	sprintf(lc1Buf, ".\\Test\\T%d.txt", siTNo);
	szpFpI = fopen(lc1Buf, "r");
	sprintf(lc1Buf, ".\\Test\\A%d.txt", siTNo);
	szpFpA = fopen(lc1Buf, "r");
	siRes = 0;
#else
	szpFpI = stdin;
#endif

	// 実行メイン
	liRet = fMain();

	// 出力
	sprintf(lc1Buf, "%d\n", liRet);
	fOutLine(lc1Buf);

	// 残データ有無
#ifdef D_TEST
	lc1Buf[0] = '\0';
	fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
	if (strcmp(lc1Buf, "")) {
		siRes = -1;
	}
#endif

	// テストファイルクローズ
#ifdef D_TEST
	fclose(szpFpI);
	fclose(szpFpA);
#endif

	// テスト結果
#ifdef D_TEST
	if (siRes == 0) {
		printf("OK %d\n", siTNo);
	}
	else {
		printf("NG %d\n", siTNo);
	}
#endif

	return 0;
}

// プログラム開始
int
main()
{

#ifdef D_TEST
	int i;
	for (i = D_TEST_SNO; i <= D_TEST_ENO; i++) {
		siTNo = i;
		fOne();
	}
#else
	fOne();
#endif

	return 0;
}