use std::vec::Vec;
use std::cmp::*;

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>().split_whitespace().map(|e| e.parse().ok().unwrap()).collect()
}

fn read_touple<T: std::str::FromStr + Copy>() -> (T, T, T) {
  let v: Vec<T> = read_vec();
  assert_eq!(v.len(), 3);
  (v[0], v[1], v[2])
}

fn main() {
    let (h, w, k) = read_touple::<usize>();
    let mut grid = vec![];
    for _ in 0..h {
      let t: Vec<char> = read::<String>().chars().collect();
      grid.push(t);
    }
    let mut ans: usize = h*w+1;

    let set = BitSet::empty(h-1);
    for b in set {
      let mut sum = vec![0; h+1];
      let bv = b.to_vec();
      let mut tot = bv.iter().fold(0, |acc, &x| if x == 1 { acc + x } else { acc });
      for i in 0..w {
        let t = calc(&grid, &bv, h, i);
        let mut ok = true;
        for i in 0..t.len() {
          if t[i] > k {
            tot = h*w+1;
            break;
          }
        }
        for i in 0..t.len() {
          sum[i] += t[i];
        }

        for i in 0..t.len() {
          if sum[i] > k {
             reset(&mut sum, &t);
             tot += 1;
             break;
          }
        }
  
      }
      if tot < ans {
        ans = tot;
        //println!("{}", tot);
        //println!("{:?}", bv);
      }
    } 

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

fn reset(v :&mut Vec<usize>, t: &Vec<usize>) {
  for i in 0..t.len() {
    v[i] = t[i];
  }
}

fn calc(grid: &Vec<Vec<char>>, bv: &Vec<usize>, h: usize, c: usize) -> Vec<usize> {
    let mut res = vec![];
    let mut now = 0;

    if grid[0][c] == '1' {
       now += 1;
    }

    for i in 1..h {
      if bv[i-1] == 1 {
        res.push(now);
         now = 0;       
      }
      if grid[i][c] == '1' {
         now += 1;
      }
    }
    res.push(now);
    //println!("{:?}", res);
    res
}


#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
struct BitSet {
    bits: usize,
    size: usize,
}

impl std::fmt::Debug for BitSet {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "BitSet {{ bits: {:b}, size: {} }}", self.bits, self.size)
    }
}

impl BitSet {
    //
    fn empty(size: usize) -> BitSet {
        if size > 64 {
            panic!("large set size")
        }
        BitSet {
            bits: 0,
            size: size,
        }
    }
    // コンンストラクター
    fn new(n: usize, size: usize) -> BitSet {
        BitSet {
            bits: n,
            size: size,
        }
    }

    // 和集合を求める
    fn union(&self, other: BitSet) -> BitSet {
        BitSet {
            bits: self.bits | other.bits,
            size: self.size, // debug
        }
    }

    // 共通部分を求める
    fn intersect(&self, other: BitSet) -> BitSet {
        BitSet {
            bits: self.bits & other.bits,
            size: self.size, // debug
        }
    }

    // n を含むかどうか
    fn include(&self, n: usize) -> bool {
        if self.size < n {
            return false;
        }
        self.bits & (1 << n) != 0
    }

    fn to_vec(&self) -> std::vec::Vec<usize> {
        let mut res = std::vec::Vec::new();
        let mut bits = self.bits;

        for _ in 0..self.size {
            res.push(bits % 2);
            bits /= 2;
        }
        res
    }

    // 集合を表すusizeの値を返す
    fn unwrap(&self) -> usize {
        self.bits
    }
}

impl Iterator for BitSet {
    type Item = BitSet;

    fn next(&mut self) -> Option<Self::Item> {
        if (1 << self.size) <= self.bits {
            return None;
        }
        self.bits += 1;
        Some(BitSet {
            bits: self.bits - 1,
            size: self.size,
        })
    }
}


Measured memory_bytes: 4352