using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using static System.Math;
using System.Text.RegularExpressions;

namespace CsharpSpiral {
    partial class Program {
        static void Main(string[] args) {
            var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            Console.SetOut(sw);
            new Program().Solve(new ConsoleInput(Console.In, ' '));
            Console.Out.Flush();
        }
        public void Solve(ConsoleInput cin) {
            var H = cin.ReadInt;
            var W = cin.ReadInt;
            var K = cin.ReadInt;
            var S = new int[H, W];
            var T = new int[H, W + 1];
            for(int i = 0; i < H; i++) {
                var row = cin.ReadLine;
                for(int j = 0; j < W; j++) {
                    S[i, j] = row[j] == '1' ? 1 : 0;
                    T[i, j + 1] = T[i, j] + S[i, j];
                    //Console.Write(T[i, j + 1]+",");
                }
                //Console.WriteLine("");
            }
            var U = new int[H + 1, W + 1];
            for(int i = 0; i < H; i++) {
                for(int j = 0; j <= W; j++) {
                    U[i + 1, j] = U[i, j] + T[i, j];
                    //Console.Write(U[i + 1, j] + ",");
                }
                //Console.WriteLine("");
            }
            var flags = Enumerable.Range(0, (1 << (H - 1)));
            Console.WriteLine(flags.Min(i => CutAndSearch(i, U, K)));
        }
        public int CutAndSearch(int flag, int[,] U, int K) {
            //Console.WriteLine($"flag:{flag}");
            var lastRow = 0;
            var rowCut = 0;
            var H = U.GetLength(0) - 1;
            Dictionary<int, int> Target2Last = new Dictionary<int, int>();
            for(int i = 1; i < H; i++) {
                if((flag & (1 << (i - 1))) != 0) {
                    Target2Last.Add(i, lastRow);
                    lastRow = i;
                    rowCut++;
                }
            }
            Target2Last.Add(H, lastRow);

            var oneColumnMax = Enumerable.Range(1, U.GetLength(1) - 1)
                .Max(j => Target2Last.Max(p => (U[p.Key, j] - U[p.Key, j - 1]) - (U[p.Value, j] - U[p.Value, j - 1])));
            if(oneColumnMax > K)
                return int.MaxValue;
            var res= Search(U, K, Target2Last) + rowCut;
            //Console.WriteLine(res);
            return res;
        }

        public int Search(int[,] U, int K, Dictionary<int,int> L) {
            //Console.WriteLine(L.Count);
            foreach(var p in L) {
                //Console.WriteLine($"{p.Key}->{p.Value}");
            }
            var W = U.GetLength(1);
            var count = 0;
            var prev = 0;
            for(int j =1; j < W; j++) {
                var K1 = L.Keys.Max(i => (U[i, j] - U[i, prev]) - (U[L[i], j] - U[L[i], prev]));
                //Console.Write(K1+",");
                if(K < K1) {
                    if(prev==j-1)return int.MaxValue;
                    count++;
                    prev = j - 1;
                }
            }
            //Console.WriteLine("");
            return count;
        }
    }

    static class ExtendClass {
        public static string Join<T>(this T[] X, string separator = " ") => string.Join(separator, X);
        public static S[] Clone<S>(this S[] src) where S : struct {
            var res = new S[src.Length];
            Array.Copy(src, res, src.Length);
            return res;
        }
    }

    class ConsoleInput {
        private readonly TextReader _stream;
        private readonly char _separator = ' ';
        private readonly Queue<string> inputStream;
        public ConsoleInput(TextReader stream, char separator = ' ') {
            this._separator = separator;
            this._stream = stream;
            inputStream = new Queue<string>();
        }
        public string Read {
            get {
                if(inputStream.Count != 0) return inputStream.Dequeue();
                string[] tmp = _stream.ReadLine().Split(_separator);
                for(int i = 0; i < tmp.Length; ++i)
                    inputStream.Enqueue(tmp[i]);
                return inputStream.Dequeue();
            }
        }
        public string ReadLine { get { return _stream.ReadLine(); } }
        public int ReadInt { get { return int.Parse(Read); } }
        public long ReadLong { get { return long.Parse(Read); } }
        public double ReadDouble { get { return double.Parse(Read); } }
        public string[] ReadStrArray(long N) {
            var ret = new string[N];
            for(long i = 0; i < N; ++i)
                ret[i] = Read;
            return ret;
        }
        public int[] ReadIntArray(long N) { var ret = new int[N]; for(long i = 0; i < N; ++i) ret[i] = ReadInt; return ret; }
        public long[] ReadLongArray(long N) { var ret = new long[N]; for(long i = 0; i < N; ++i) ret[i] = ReadLong; return ret; }
        public double[] ReadDoubleArray(long N) { var ret = new double[N]; for(long i = 0; i < N; ++i) ret[i] = ReadDouble; return ret; }
    }
}


Measured memory_bytes: 19720