#include<bits/stdc++.h>
using namespace std;
int row[11][1001], col[11][1001];

//Cuts vector stores the position where cuts are to be made
void thunder(int h, int w, int k, int ind, int &ans, vector<int>&cuts){
    //We can't mark any cut at end
    //Base Case
//    cout<<"H";
    if(ind == h){
//        cout<<"B";
        cuts.push_back(h);
        //All possible cases would reach here
        //Some cases might be not possible-- Removing those first;
        int n=cuts.size();
        for(int i=1; i<n; i++){
            //If sum of any column between two cuts > k return
            for(int j=1; j<=w; j++){
                if((col[cuts[i]][j]-col[cuts[i-1]][j])>k){
                    cuts.pop_back();
                    return ;
                }
            }
        }
//        cout<<"Vertical cuts: ";
//        for(int i=0; i<n; i++){
//            cout<<cuts[i]<<" ";
//        }
//        cout<<"\nHorizontal cuts: ";
        //Now we do not have any column where sum is > k
        //Now let's create blocks
        int colcuts = 0;
        for(int j=0; j<w; j++){
            // j is the starting column;
            int tp=j+1;
            int tpp[n];
            memset(tpp, 0, sizeof(tpp));
            for(int i=1; i<n; i++){
                tpp[i] = col[cuts[i]][j] - col[cuts[i-1]][j];
            }
            bool flag = true;
//            cout<<"tpp: "<<tpp<<" ";
            while(tp<=w){
//                cout<<tp<<" : ";
                //Checking the sum of block formed by [j, k];
                for(int i=1; i<n && flag; i++){
//                    cout<<tpp[i]<<" ("<<col[cuts[i]][tp]-col[cuts[i-1]][tp]<<") ";
                    if((col[cuts[i]][tp]-col[cuts[i-1]][tp]+tpp[i]) <= k){
                        //adding tp'th column can also be included
                        tpp[i] += col[cuts[i]][tp]-col[cuts[i-1]][tp];
                    }else{
//                        cout<<"Broke\n";
                        flag = false;
                    }
                }
//                cout<<endl;
                if(flag==false){
                    break;
                }
                tp++;
            }
//            cout<<j<< " : " <<tp-1<<endl;
//            cout<<endl;
            if(tp <= w){
//                cout<<tp-1<<" ";
                colcuts++;
            }
            j = tp-1;
        }
//        cout<<endl;
//        cout<<colcuts<<" "<<n-2<<endl;
        ans = min(ans, colcuts+n-2);
        cuts.pop_back();
        return;
    }
    //If we made a cut
    thunder(h, w, k, ind+1, ans, cuts);
    cuts.push_back(ind);
    thunder(h, w, k, ind+1, ans, cuts);
    cuts.erase(prev(cuts.end()));
//    cuts.pop_back();
    //If we do not make a cut
}

int main(){
    int h,w,k;
    cin>>h>>w>>k;
    string s[h];
    //row stores horizontal sum of ith row upto jth column
    //col stores vertical sum of jth column upto ith row
    for(int i=0; i<=h; i++){
        if(i!=h){
            cin>>s[i];
        }
        for(int j=0; j<=w; j++){
            if(i==0 || j==0){
                col[i][j] = 0;
                row[i][j] = 0;
            }
            else{
                int curr = (s[i-1][j-1]=='1') ? 1 : 0;
                col[i][j] = col[i-1][j]+curr;
                row[i][j] = row[i][j-1]+curr;
            }
        }
    }
//    for(int i=0; i<=h; i++){
//        for(int j=0; j<=w; j++){
//            cout<<row[i][j]<<" ";
//        }
//        cout<<endl;
//    }
    int ans = INT_MAX;
    vector<int>cuts;
    cuts.push_back(0);
    //Current row where we are working upon
    thunder(h, w, k, 1, ans, cuts);
    cout<<ans<<endl;
    return 0;
}


Measured memory_bytes: 384