#include <iostream>
#include <vector>
#include <queue>
#include <math.h>
#include <unordered_map>
#include <cstring>
#include <algorithm>
#include <set>
#include <climits>
#include <numeric>

//usings
using namespace std;

//type def
typedef long long int64;
typedef pair<int, int> ii;

//consts
const int mod = 1e9 + 7;

//methods
template<typename T>
bool chmax(T& source, const T& compare_to) {
    if(source < compare_to) {
        source = compare_to;
        return true;
    }
    return false;
}

int modpow(int64 base, int n) {
    int64 ret = 1;
    while(n) {
        if(n & 1) ret = ret * base % mod;
        base = base * base % mod;
        n >>= 1;
    }
    return ret;
}

template<typename T>
void dump(vector<T> container) {
    for(const auto& i : container) cout << i << " ";
    cout << endl;
}

template<typename T>
void dump(vector<vector<T>> container) {
    for(const auto& v : container) {
        for(const auto& i : v) cout << i << " ";
        cout << endl;
    }
}

class Solution {
private:
public:
    int m, n;
    int solve(int m, int n, int k, vector<string>& grid) {
        int ret = INT_MAX;
        this->m = m, this->n = n;
        vector<vector<int>> pre_cnt(m + 1, vector<int>(n + 1));
        for(int i = 1; i <= m; ++i) {
            for(int j = 1; j <= n; ++j) {
                pre_cnt[i][j] = pre_cnt[i][j - 1] + pre_cnt[i - 1][j] - pre_cnt[i - 1][j - 1] + (grid[i - 1][j - 1] == '1'); 
            }
        }
        // dump(pre_cnt);
        for(int i = 0; i < 1 << (m - 1); ++i) {
            int cuts_cnt = __builtin_popcount(i), cut_idx = 0;
            // cout << "cuts cnt: " << cuts_cnt << ", mask: " << i << endl;
            while(cut_idx < n) {
                //binary search
                int l = cut_idx + 1, h = n + 1;
                while(h > l + 1) {
                    int mid = (l + h) / 2;
                    if(max_cnt(cut_idx, mid, i, pre_cnt) <= k) l = mid;
                    else h = mid;
                }
                auto mcnt = max_cnt(cut_idx, l, i, pre_cnt);
                // cout << "l: " << l << ", h: " << h << ", mcnt: " << mcnt << ", cut_idx: " << cut_idx << endl;
                
                if(mcnt <= k) ++cuts_cnt;
                else {
                    cuts_cnt = INT_MAX;
                    break;
                }
                cut_idx = l;
            }
            ret = min(ret, cuts_cnt - 1);
        }
        return ret;
    }

    int max_cnt(int cut_idx_left, int cut_idx_right, int row_mask, const vector<vector<int>>& pre_cnt) {
        int row_idx = 0, cnt = 0;
        for(int i = 0; i < m - 1; ++i) {
            if(row_mask & (1 << i)) {
                cnt = max(cnt, cnt_white(row_idx, cut_idx_left, i + 1, cut_idx_right, pre_cnt));
                row_idx = i + 1;
            }
        }
        cnt = max(cnt, cnt_white(row_idx, cut_idx_left, m, cut_idx_right, pre_cnt));
        return cnt;
    }

    int cnt_white(int x1, int y1, int x2, int y2, const vector<vector<int>>& cnt) {
        return cnt[x2][y2] - cnt[x2][y1] - cnt[x1][y2] + cnt[x1][y1];
    }
};

int main() {
    int m, n, k;
    cin >> m >> n >> k;
    vector<string> grid(m);
    for(int i = 0; i < m; ++i) cin >> grid[i];
    Solution sol;
    auto ret = sol.solve(m, n, k, grid);
    cout << ret << endl;
}

Measured memory_bytes: 256