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# (Mono 4.6.2.0) (judge verdict: Accepted)

/*******************************************c#
* 20.05.07 AtCoder Beginner Contest 159. E - Dividing Chocolate
*
*
*********************************************/
/*********************************************

問題文
縦 H マス、横 W マスのグリッドに区切られたチョコレートがあります。

上から i 行目、左から j 列目にあるマス (i,j) のチョコレートは、
Si,j が 0 のとき普通のチョコレートであり、1 のときホワイトチョコレートです。

このチョコレートに対して、マスの境界に沿った直線によってグリッド全体の端から
端まで割る操作を何度か行い、いくつかのブロックに分割します。

分割後のどのブロックにもホワイトチョコレートのマスが K マス以下しか含まれない
ようにするためには、最小で操作を何回行う必要があるか求めてください。

::editorial::
もし「縦方向にしか割れない」という条件があれば、左端から順に貪欲にとることで問題を解くこ
とができます。よって、「横方向にどう割るか」を 2
H−1 通り全探索し、それぞれの場合について「縦
方向にしか割れない」問題を解けばよいです。計算量は O(2HHW) です。


::test input::
3 5 4
11100
10001
00111

*********************************************/
namespace TempName{
    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.Reflection;
    using static System.Console;
    using static IOmacro.CInput; 
    using static IOmacro.CppInput;
    using static STLExtension.CppExtension;
    
    public class CRun{
        public void solve() {
            
            int H = cin;
            int W = cin;
            int K = cin;
            var S = new int[H][];
            for (int i=0; i<H; i++) {
                string input = _string;
                S[i] = new int[input.Length];
                for (int j=0; j<input.Length; j++) {
                    S[i][j] = input[j] - 48;
                }
            }
            
            int ans = int.MaxValue;
            
            for (int bits = 0; bits < 1<<(H-1); bits++) {
                
                //nCr 횡긋기
                int true_bits = PopCount(bits);
                int ans_now = true_bits;
                int section_num = true_bits +1;
                
                //그은 경우의수에 따른 섹션나누기
                //값이 같으면 같은 섹션 (ex: 0, 0, 1, 1, 2)
                var section_y = new int[H];
                for (int y = 0; y < H -1; y++) {
                    section_y[y +1] = section_y[y] + (bits >> y & 1);
                }
                
                var chocos = new int[section_num];
                for (int x = 0; x < W; x++) {
                    for (int y = 0; y < H; y++) {
                        if (S[y][x] == 1) chocos[section_y[y]] +=1;
                    }
                    
                    if (chocos.Any(vcx => vcx > K)) {
                        ans_now +=1;
                        Array.Clear(chocos, 0, chocos.Length);
                        for (int y = 0; y < H; y++) {
                            if (S[y][x] == 1) chocos[section_y[y]] +=1;
                        }
                        if (chocos.Any(vcx => vcx > K)) {
                            goto end;
                        }
                    }
                    
                }
                ans = Math.Min(ans, ans_now);
                end:;
            }
            
            WriteLine(ans);
        }
    }
    
    class Program { 
        static void Main() { 
            var run = new CRun();
            run.solve();
        } 
    }
}

namespace IOmacro {
    //20.05.05. 수정
    
    using System; 
    using System.Linq; 
    using System.IO;
    using System.Collections.Generic;
    
    public class CInput {
        public static StreamWriter _writer = new StreamWriter(Console.OpenStandardOutput());
        public const char separator = ' ';
        public static string _string{get{return Console.ReadLine();}}
        public static string[] _stringa{get{return (Console.ReadLine().Split(separator));}}
        public static int _int{get{return int.Parse(Console.ReadLine());}}
        public static int[] _inta{get{return Console.ReadLine().Split(separator).Select(int.Parse).ToArray();}}
        public static long _long{get{return long.Parse(Console.ReadLine());}}
        public static long[] _longa{get{return Console.ReadLine().Split(separator).Select(long.Parse).ToArray();}}    
        public static double _double{get{return double.Parse(Console.ReadLine());}}
        public static double[] _doublea{get{return Console.ReadLine().Split(separator).Select(double.Parse).ToArray();}}    
    }
    
    public class CConst {
        public static readonly int MINI = int.MaxValue;
        public static readonly long INF = Int64.MaxValue;
    }
    
    public class CppInput {
        public static CppInput cin => new CppInput();
        public const char separator = ' ';
        private static readonly Queue<string> _input = new Queue<string>();
        private CppInput(){}
        public static implicit operator string(CppInput _) {
            if (_input.Count == 0) Console.ReadLine().Split(separator).foreachExtension(x => _input.Enqueue(x));
            return _input.Dequeue();
        }
        public static implicit operator int(CppInput _){
            if (_input.Count == 0) Console.ReadLine().Split(separator).foreachExtension(x => _input.Enqueue(x));
            return int.Parse(_input.Dequeue());
        }
        public static implicit operator long(CppInput _){
            if (_input.Count == 0) Console.ReadLine().Split(separator).foreachExtension(x => _input.Enqueue(x));
            return long.Parse(_input.Dequeue());
        }
        public static implicit operator double(CppInput _){
            if (_input.Count == 0) Console.ReadLine().Split(separator).foreachExtension(x => _input.Enqueue(x));
            return double.Parse(_input.Dequeue());
        }
    }
    
    public static class EnumerableExtension {
        public delegate void Function<in T>(T val);
        public static void foreachExtension<T>(this IEnumerable<T> enumerable, Function<T> function) {
            foreach (var x in enumerable) function(x);
        }
    }
}

namespace STLExtension {
    //20.05.05. 수정
    
    public class CppExtension {
        public static int PopCount(int n) {
            //A SWAR Algorithm for Popcount
            //비트의 1의 개수
            int msb = 0;
            if (n < 0) { n &= int.MaxValue; msb = 1; }
            n = n - ((n >> 1) & 0x55555555);
            n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
            return (int)(((n + (n >> 4) & 0xF0F0F0F) * 0x1010101) >> 24) + msb;
        }
    }
}