#include <bits/stdc++.h>
using namespace std;

#pragma region Macros
using ll = long long;
using pii = pair<int, int>;
using tiii = tuple<int, int, int>;
template<class T = ll> using V = vector<T>;
template<class T = ll> using VV = V<V<T>>;
#define int ll
#define IOS\
    ios::sync_with_stdio(false);\
    cin.tie(0);\
    cout.tie(0);
#define FOR(i,l,r) for(ll i=(l);i<(r);++i)
#define REP(i,n) FOR(i,0,n)
#define REPS(i,n) FOR(i,1,n+1)
#define RFOR(i,l,r) for(ll i=(l);i>=(r);--i)
#define RREP(i,n) RFOR(i,n-1,0)
#define RREPS(i,n) RFOR(i,n,1)
#define pb push_back
#define eb emplace_back
#define all(x) (x).begin(),(x).end()
#define SORT(name) sort(name.begin(), name.end())
#define RSORT(name)\
    SORT(name);\
    reverse(all(name));
#define ZERO(p) memset(p, 0, sizeof(p))
#define MINUS(p) memset(p, -1, sizeof(p))
#if 0
#  define DBG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#  define DBG(fmt, ...)
#endif
inline void Yes(bool b = true) {cout << (b ? "Yes" : "No") << '\n';}
inline void YES(bool b = true) {cout << (b ? "YES" : "NO") << '\n';}
template <class T> inline void print(T x){ cout << x << '\n';}
template<typename T1,typename T2> inline void chmin(T1 &a, T2 b){ if(a > b) a = b; }
template<typename T1,typename T2> inline void chmax(T1 &a, T2 b){ if(a < b) a = b; }

const ll LLINF = (1LL<<60);
const int INF = (1LL<<30);
const double DINF = std::numeric_limits<double>::infinity();
const int MOD = 1000000007;
#pragma endregion

template< class T >
class CumulativeSum2D
{
public:
    vector< vector< T > > m_data;

    CumulativeSum2D(int W, int H) : m_data(W + 1, vector< int >(H + 1, 0)) {}

    // 要素 (x,y) に値 z を加える O(1)
    void Add(int x, int y, int z) {
        ++x, ++y;
        if(x >= m_data.size() || y >= m_data[0].size()) { return; }
        m_data[x][y] += z;
    }

    // 累積和の構築 O(WH)
    void Build() {
        for(int i = 1; i < m_data.size(); i++) {
            for(int j = 1; j < m_data[i].size(); j++) {
                m_data[i][j] += m_data[i][j - 1] + m_data[i - 1][j] - m_data[i - 1][j - 1];
            }
        }
    }

    // 左上 [sx, sy], 右下(gx, gy) の矩形内の和を求める O(1)
    // 右下は含まないので注意
    T Query(int sx, int sy, int gx, int gy) {
        return (m_data[gx][gy] - m_data[sx][gy] - m_data[gx][sy] + m_data[sx][sy]);
    }
};

const int MAX_N = 100010;

int H, W, K;
V<string> S;

// 横線の引き方が pat の時に必要な縦線の数を返す
// 不可能なら -1 を返す
int func(CumulativeSum2D<int>& cs, int pat) {
    // パターンから区間に変換
    V<pii> range;
    int y_base = 0;
    REP(y, (H - 1)) {
        if((pat >> y) & 1) {
            range.pb(make_pair(y_base, y + 1));
            y_base = y + 1;
        }
    }
    range.pb(make_pair(y_base, H));

    int ret = 0;
    int x_base = 0;
    REPS(x, W) {
        // 各長方形が問題ないか？
        for(auto& range_tmp : range) {
            int sy = range_tmp.first;
            int gy = range_tmp.second;
            int cnt = cs.Query(x_base, sy, x, gy);
            if(cnt > K) {
                // 幅 1 なら無理
                if(x - x_base <= 1) { return -1; }
                x_base = x - 1;
                x = x_base;
                ret++;
                break;
            }
        }
    }
    return ret;
}

signed main() {
    IOS;

    cin >> H >> W >> K;
    S.resize(H);
    REP(i, H) {
        cin >> S[i];
    }

    CumulativeSum2D<int> cs(W, H);

    REP(i, H) {
        REP(j, W) {
            if (S[i][j] == '1') {
                cs.Add(j, i, 1);
            }
        }
    }
    cs.Build();

    int ans = LLINF;
    for(int pat = 0; pat < (1 << (H - 1)); ++pat) {
        int cand = func(cs, pat);
        if (cand >= 0) {
            chmin(ans, cand + __builtin_popcountll(pat));
        }
    }
    print(ans);

    return 0;
}


Measured memory_bytes: 3736