#![allow(unused)]

use std::io::{Read, StdinLock};
use std::iter::{FromIterator, Iterator};
use std::str::{FromStr};
use std::string::String;
use std::ops::{BitAnd, Shl};
use std::convert::{From};
use std::slice::IterMut;

macro_rules! debug {
    ($($a:expr),*) => {
	println!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
    }
}

pub fn read_bytes<T: FromIterator<char>>(s: &mut StdinLock) -> T {
    s.bytes()
        .map(|c| c.unwrap() as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect::<T>()
}

pub fn reads(s: &mut StdinLock) -> String {
    read_bytes::<String>(s)
}

pub fn read<T: FromStr>(s: &mut StdinLock) -> T {
    reads(s).parse().ok().unwrap()
}

trait IteratorExt<'a>: Iterator {
    fn copy<U>(self, other: U)
    where
        Self::Item: 'a + Clone,
        U: Iterator<Item = &'a mut Self::Item>;
}

// impl<'a, I, T> if necessary
impl<'a, I> IteratorExt<'a> for I
where
    I: Iterator,
{
    fn copy<U>(self, other: U)
    where
        Self::Item: 'a + Clone,
        U: Iterator<Item = &'a mut Self::Item>
    {
        for (x, y) in self.zip(other) {
            *y = x;
        }
    }
}

//==============================================================================
//
// Problem specific code
//
//==============================================================================

const H_MAX: usize = 10;

struct Problem {
    h: usize,
    w: usize,
    k: i64,
    choco: Vec<Vec<i64>>,
}

fn is_set<T>(b: T, i: usize) -> bool
where
    T: Eq + From<u8> + BitAnd<T, Output=T> + Shl<usize, Output=T>
{
    let zero = T::from(0u8);
    let one = T::from(1u8);
    let mask: T = one << i;
    let and: T = b & mask;
    and != zero
}

// hsplits = [0, split1, split2, ..., h]
fn split_vert(p: &Problem, hsplitbits: u16) -> Option<usize> {
    let mut hmap = [0; H_MAX];
    (0..(p.h - 1))
        .scan(0, |s, i| {
            *s += if is_set(hsplitbits, i) { 1 } else { 0 };
            Some(*s)
        })
        .copy(hmap[1..].iter_mut());

    let nhsplit = hmap[p.h - 1];
    let mut counts = [0i64; H_MAX];
    let mut nvsplit = 0;

    for x in 0..p.w {
        let mut counts_ = [0i64; H_MAX];
        for y in 0..p.h {
            counts_[hmap[y]] += p.choco[x][y];
        }

        if counts_.into_iter().any(|&c| c > p.k) {
            return None;  // unsatisfiable
        }
        for s in 0..(nhsplit + 1) {
            counts[s] += counts_[s];
        }
        if counts.into_iter().any(|&c| c > p.k) {
            nvsplit += 1;
            counts = counts_;
        }
    }

    Some(nhsplit + nvsplit)
}

fn transpose(mat: &Vec<Vec<i64>>) -> Vec<Vec<i64>> {
    if mat.len() == 0 || mat[0].len() == 0 {
        return Vec::new();
    }

    (0..mat[0].len())
        .map(|j| (0..mat.len()).map(|i| mat[i][j]).collect())
        .collect()
}

fn main() {
    let sin = std::io::stdin();
    let mut sin = sin.lock();

    let h = read::<usize>(&mut sin);
    let w = read::<usize>(&mut sin);
    let k = read::<i64>(&mut sin);

    let choco = (0..h).map(|_| {
            read_bytes::<Vec<char>>(&mut sin)
                .into_iter()
                .map(|c| if c == '0' { 0 } else { 1 })
                .collect::<Vec<_>>()
        })
        .collect::<Vec<_>>();

    let p = Problem { h: h, w: w, k: k, choco: transpose(&choco) };

    let ans = (0u16..(1u16 << (h - 1))).flat_map(|b| split_vert(&p, b)).min().unwrap();

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



Measured memory_bytes: 4352