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 Rust (1.42.0) (judge verdict: Accepted)

#![allow(non_snake_case, unused_variables, dead_code)]
//use permutohedron::LexicalPermutation as _;
//use proconio::input;
use proconio::marker::Chars;
//use proconio::marker::Usize1;
//use std::collections::HashSet;
//use std::collections::HashMap;
//use std::collections::BTreeMap;
//use std::cmp::*;
//use std::num;

fn main() {
    proconio::input! {
        H:usize,W:usize,K:u32,
        S:[Chars;H]
    }
    let S: Vec<Vec<u32>> = S
        .iter()
        .map(|Si| Si.iter().map(|&c| (c as u8 - '0' as u8) as u32).collect())
        .collect();
    // Hの分割法を0から2^H-1まで総当たりで試す。
    // h_bar[i]==trueなら、i行目とi+1行目の間が結合していることを示す。
    // 逆にいうと、h_bar[i]==trueの行の数は、次の行の数に足す。
    // なお、H_bar[H-1]は常にfalseなので、次の行に足してしまうことは無い。
    // div がその時の分割数。
    let mut ans = H + W;
    let mut h_bar = vec![false; H];
    for h_devide in 0..(2i32.pow(H as u32 - 1)) {
        let mut div = h_devide.count_ones() as usize;
        for i in 0..H - 1 {
            h_bar[i] = (h_devide >> i) & 1 == 0;
        }
        //println!("h_devide {:?},{}", h_bar, div);
        // 以下、W方向について貪欲法。
        let mut white = vec![0; H];
        let mut w_len = 0;
        let mut w = 0;
        while w < W {
            //   println!("{}", w);
            let mut w_flag = true;
            for h in 0..H {
                // 各行を最大数がKになるまで結合していく。
                white[h] += S[h][w];
                if h_bar[h] {
                    white[h + 1] += white[h];
                    white[h] = 0;
                }
                if white[h] > K {
                    w_flag = false;
                    break;
                }
            }
            if !w_flag {
                // Kを超えてしまったら、分割を追加し、whiteを初期化して、同じ列をやり直す。
                // この時w_lenをリセット
                if w_len == 0 {
                    // ただし一行も追加できかった場合は打ち切り。
                    div = H + W;
                    break;
                }
                div += 1;
                white = vec![0; H];
                w_len = 0;
                continue;
            }
            // 無事に1列追加出来たら。
            w_len += 1;
            w += 1;
        }
        //println!("h分割{:?}, 計{}", h_bar, div);
        ans = std::cmp::min(ans, div);
    }

    println!("{}", ans);
}