Problem p02733 (C++)

Buggy submission (status: Runtime Error):
// #define NDEBUG

#pragma GCC optimize("O3") // 最適化レベルの変更 O0〜O3 などを指定
#pragma GCC optimize("-O3,inline,omit-frame-pointer,unroll-loops")
#pragma warning(1 : 4456) // 多重forループ内での変数の２重定義を警告にする

#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES

#include <iostream>

#include <algorithm>
#include <array>
#include <bitset>
#include <cmath>
#include <fstream>
#include <iomanip>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <cassert>
#include <memory>

#include <chrono>
#include <functional>

using namespace std;

namespace ValLib {

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;

constexpr ull V_MOD = 1000000007ull;
constexpr int V_INT_MAX = 2147483647;
constexpr ll V_LL_MAX = 9223372036854775807ll;
constexpr ull V_ULL_MAX = 18446744073709551615ull;

template <typename Key, typename Value>
using umap = std::unordered_map<Key, Value>;
template <typename T> using uset = std::unordered_set<T>;

template <typename T> void fill(vector<T> &vec, const T &value) {
  std::fill(vec.begin(), vec.end(), value);
}
template <typename T> void fill(vector<vector<T>> &vec, const T &value) {
  for (vector<T> &t : vec)
    std::fill(t.begin(), t.end(), value);
}
template <typename T> void resize(vector<T> &vec, int size1) {
  vec.resize(size1);
}
template <typename T> void resize(vector<T> &vec, int size1, const T &value) {
  vec.resize(size1, value);
}
template <typename T>
void resize(vector<vector<T>> &vec, int size1, int size2) {
  vec.resize(size1);
  for (vector<T> &t : vec)
    t.resize(size2);
}
template <typename T>
void resize(vector<vector<T>> &vec, int size1, int size2, const T &value) {
  vec.resize(size1);
  for (vector<T> &t : vec)
    t.resize(size2, value);
}
template <typename T> void assign(vector<T> &vec, int size1, const T &value) {
  vec.assign(size1, value);
}
template <typename T>
void assign(vector<vector<T>> &vec, int size1, int size2, const T &value) {
  vec.resize(size1);
  for (vector<T> &t : vec)
    t.assign(size2, value);
}
template <typename T>
const typename vector<T>::const_iterator max_element(const vector<T> &vec) {
  assert(!vec.empty());
  return std::max_element(vec.begin(), vec.end());
}
template <typename T, typename _Pr>
const typename vector<T>::const_iterator max_element(const vector<T> &vec,
                                                     _Pr lessThan) {
  assert(!vec.empty());
  return std::max_element(vec.begin(), vec.end(), lessThan);
}
template <typename T> typename vector<T>::iterator min_element(vector<T> &vec) {
  assert(!vec.empty());
  return std::min_element(vec.begin(), vec.end());
}
template <typename T>
const typename vector<T>::const_iterator min_element(const vector<T> &vec) {
  assert(!vec.empty());
  return std::min_element(vec.begin(), vec.end());
}
template <typename T, typename _Pr>
const typename vector<T>::const_iterator min_element(const vector<T> &vec,
                                                     _Pr lessThan) {
  assert(!vec.empty());
  return std::min_element(vec.begin(), vec.end(), lessThan);
}
int accumulate(const vector<int> &vec) {
  return std::accumulate(vec.begin(), vec.end(), 0);
}
template <typename _Pr> int accumulate(const vector<int> &vec, _Pr func) {
  return std::accumulate(vec.begin(), vec.end(), 0, func);
}
double accumulate(const vector<double> &vec) {
  return std::accumulate(vec.begin(), vec.end(), 0.0);
}
template <typename _Pr> double accumulate(const vector<double> &vec, _Pr func) {
  return std::accumulate(vec.begin(), vec.end(), 0.0, func);
}
float accumulate(const vector<float> &vec) {
  return std::accumulate(vec.begin(), vec.end(), 0.f);
}
template <typename _Pr> float accumulate(const vector<float> &vec, _Pr func) {
  return std::accumulate(vec.begin(), vec.end(), 0.f, func);
}
template <typename T, typename _Pr>
bool all_of(const vector<T> &vec, _Pr pred) {
  return std::all_of(vec.begin(), vec.end(), pred);
}
template <typename T, typename _Pr>
bool any_of(const vector<T> &vec, _Pr pred) {
  return std::any_of(vec.begin(), vec.end(), pred);
}
template <typename T, typename _Pr>
bool none_of(const vector<T> &vec, _Pr pred) {
  return std::none_of(vec.begin(), vec.end(), pred);
}
template <typename T>
const typename vector<T>::const_iterator find(const vector<T> &vec,
                                              const T &val) {
  return std::find(vec.begin(), vec.end(), val);
}
template <typename T, typename _Pr>
const typename vector<T>::const_iterator find_if(const vector<T> &vec,
                                                 _Pr pred) {
  return std::find_if(vec.begin(), vec.end(), pred);
}
template <typename T> bool contains(const vector<T> &vec, const T &val) {
  return std::find(vec.begin(), vec.end(), val) != vec.end();
}
template <typename T, typename _Pr>
bool contains_if(const vector<T> &vec, _Pr pred) {
  return std::find_if(vec.begin(), vec.end(), pred) != vec.end();
}
template <typename T, typename _Pr>
typename iterator_traits<
    const typename vector<T>::const_iterator>::difference_type
count_if(const vector<T> &vec, _Pr pred) {
  return std::count_if(vec.begin(), vec.end(), pred);
}
template <typename T> void sort(vector<T> &vec) {
  std::sort(vec.begin(), vec.end());
}
template <typename T, typename _Pr> void sort(vector<T> &vec, _Pr pred) {
  std::sort(vec.begin(), vec.end(), pred);
}
template <typename T> void stable_sort(vector<T> &vec) {
  std::stable_sort(vec.begin(), vec.end());
}
template <typename T, typename _Pr> void stable_sort(vector<T> &vec, _Pr pred) {
  std::stable_sort(vec.begin(), vec.end(), pred);
}

template <typename T, size_t N> void fill(array<T, N> &ary, const T &value) {
  std::fill(ary.begin(), ary.end(), value);
}
template <typename T, size_t N, size_t M>
void fill(array<array<T, M>, N> &ary, const T &value) {
  for (array<T, M> &t : ary)
    std::fill(t.begin(), t.end(), value);
}
template <typename T, size_t N, typename _Pr>
const typename array<T, N>::const_iterator max_element(const array<T, N> &ary) {
  assert(!ary.empty());
  return std::max_element(ary.begin(), ary.end());
}
template <typename T, size_t N, typename _Pr>
const typename vector<T>::const_iterator max_element(const array<T, N> &ary) {
  assert(!ary.empty());
  return std::max_element(ary.begin(), ary.end());
}
template <typename T, size_t N, typename _Pr>
const typename array<T, N>::const_iterator max_element(const array<T, N> &ary,
                                                       _Pr lessThan) {
  assert(!ary.empty());
  return std::max_element(ary.begin(), ary.end(), lessThan);
}
template <typename T, size_t N, typename _Pr>
const typename array<T, N>::const_iterator min_element(const array<T, N> &ary) {
  assert(!ary.empty());
  return std::min_element(ary.begin(), ary.end());
}
template <typename T, size_t N, typename _Pr>
const typename array<T, N>::const_iterator min_element(const array<T, N> &ary,
                                                       _Pr lessThan) {
  assert(!ary.empty());
  return std::min_element(ary.begin(), ary.end(), lessThan);
}
template <size_t N> int accumulate(const array<int, N> &ary) {
  return std::accumulate(ary.begin(), ary.end(), 0);
}
template <size_t N, typename _Pr>
int accumulate(const array<int, N> &ary, _Pr func) {
  return std::accumulate(ary.begin(), ary.end(), 0, func);
}
template <size_t N> double accumulate(const array<double, N> &ary) {
  return std::accumulate(ary.begin(), ary.end(), 0.0);
}
template <size_t N, typename _Pr>
double accumulate(const array<double, N> &ary, _Pr func) {
  return std::accumulate(ary.begin(), ary.end(), 0.0, func);
}
template <size_t N> float accumulate(const array<float, N> &ary) {
  return std::accumulate(ary.begin(), ary.end(), 0.f);
}
template <size_t N, typename _Pr>
float accumulate(const array<float, N> &ary, _Pr func) {
  return std::accumulate(ary.begin(), ary.end(), 0.f, func);
}
template <typename T, size_t N, typename _Pr>
bool all_of(const array<T, N> &ary, _Pr pred) {
  return std::all_of(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N, typename _Pr>
bool any_of(const array<T, N> &ary, _Pr pred) {
  return std::any_of(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N, typename _Pr>
bool none_of(const array<T, N> &ary, _Pr pred) {
  return std::none_of(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N>
const typename array<T, N>::const_iterator find(const array<T, N> &ary,
                                                const T &val) {
  return std::find(ary.begin(), ary.end(), val);
}
template <typename T, size_t N, typename _Pr>
const typename array<T, N>::const_iterator find_if(const array<T, N> &ary,
                                                   _Pr pred) {
  return std::find_if(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N>
bool contains(const array<T, N> &ary, const T &val) {
  return std::find(ary.begin(), ary.end(), val) != ary.end();
}
template <typename T, size_t N, typename _Pr>
bool contains_if(const array<T, N> &ary, _Pr pred) {
  return std::find_if(ary.begin(), ary.end(), pred) != ary.end();
}
template <typename T, size_t N, typename _Pr>
typename iterator_traits<
    const typename array<T, N>::const_iterator>::difference_type
count_if(const array<T, N> &ary, _Pr pred) {
  return std::count_if(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N> void sort(array<T, N> &ary) {
  std::sort(ary.begin(), ary.end());
}
template <typename T, size_t N, typename _Pr>
void sort(array<T, N> &ary, _Pr pred) {
  std::sort(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N> void stable_sort(array<T, N> &ary) {
  std::stable_sort(ary.begin(), ary.end());
}
template <typename T, size_t N, typename _Pr>
void stable_sort(array<T, N> &ary, _Pr pred) {
  std::stable_sort(ary.begin(), ary.end(), pred);
}

template <typename Key, typename Value>
bool containsKey(const umap<Key, Value> &m, const Key &key) {
  return m.find(key) != m.end();
}
template <typename Key, typename Value>
bool containsValue(const umap<Key, Value> &m, const Value &val) {
  for (auto it = m.begin(); it != m.end(); ++it)
    if (it->second == val)
      return true;
  return false;
}
template <typename T>
const typename uset<T>::const_iterator find(const uset<T> &s, const T &key) {
  return s.find(key);
}
template <typename T> bool contains(const uset<T> &s, const T &key) {
  return s.find(key) != s.end();
}

constexpr int DX4[] = {0, -1, 0, 1};
constexpr int DY4[] = {-1, 0, 1, 0};
constexpr int DX8[] = {0, -1, -1, -1, 0, 1, 1, 1};
constexpr int DY8[] = {-1, -1, 0, 1, 1, 1, 0, -1};

constexpr int DX5[] = {DX4[0], DX4[1], DX4[2], DX4[3], 0};
constexpr int DY5[] = {DY4[0], DY4[1], DY4[2], DY4[3], 0};
constexpr int DX9[] = {DX8[0], DX8[1], DX8[2], DX8[3], DX8[4],
                       DX8[5], DX8[6], DX8[7], 0};
constexpr int DY9[] = {DY8[0], DY8[1], DY8[2], DY8[3], DY8[4],
                       DY8[5], DY8[6], DY8[7], 0};

class Point {
public:
  constexpr inline Point() : Point(-1, -1) {}
  constexpr inline Point(int x, int y) : x(x), y(y) {}

  static Point getManhattanDist(const Point &p1, const Point &p2) {
    return move(Point(abs(p1.x - p2.x), abs(p1.y - p2.y)));
  }

  void setPos(const Point &pos) {
    x = pos.x;
    y = pos.y;
  }
  void setPos(int x, int y) {
    this->x = x;
    this->y = y;
  }

  Point operator+(int val) const { return move(Point(x + val, y + val)); }
  Point operator-(int val) const { return move(Point(x - val, y - val)); }
  Point operator*(int val) const { return move(Point(x * val, y * val)); }
  Point operator/(int val) const { return move(Point(x / val, y / val)); }
  Point operator+(const Point &p) const {
    return move(Point(x + p.x, y + p.y));
  }
  Point operator-(const Point &p) const {
    return move(Point(x - p.x, y - p.y));
  }
  Point operator*(const Point &p) const {
    return move(Point(x * p.x, y * p.y));
  }
  Point operator/(const Point &p) const {
    return move(Point(x / p.x, y / p.y));
  }
  void operator+=(int val) {
    x += val;
    y += val;
  }
  void operator-=(int val) {
    x -= val;
    y -= val;
  }
  void operator*=(int val) {
    x *= val;
    y *= val;
  }
  void operator/=(int val) {
    x /= val;
    y /= val;
  }
  void operator+=(const Point &p) {
    x += p.x;
    y += p.y;
  }
  void operator-=(const Point &p) {
    x -= p.x;
    y -= p.y;
  }
  void operator*=(const Point &p) {
    x *= p.x;
    y *= p.y;
  }
  void operator/=(const Point &p) {
    x /= p.x;
    y /= p.y;
  }
  bool operator==(const Point &p) const { return x == p.x && y == p.y; }
  bool operator!=(const Point &p) const { return x != p.x || y != p.y; }
  // bool operator<(const Point &p) const {return x * x + y * y < p.x * p.x +
  // p.y * p.y;}
  const Point &getPos() const { return *this; }

  string to_string() const {
    return "(" + std::to_string(x) + ", " + std::to_string(y) + ")";
  }

  int x, y;
};

constexpr Point DP4[] = {Point(DX4[0], DY4[0]), Point(DX4[1], DY4[1]),
                         Point(DX4[2], DY4[2]), Point(DX4[3], DY4[3])};
constexpr Point DP5[] = {Point(DX5[0], DY5[0]), Point(DX5[1], DY5[1]),
                         Point(DX5[2], DY5[2]), Point(DX5[3], DY5[3]),
                         Point(DX5[4], DY5[4])};
constexpr Point DP8[] = {Point(DX8[0], DY8[0]), Point(DX8[1], DY8[1]),
                         Point(DX8[2], DY8[2]), Point(DX8[3], DY8[3]),
                         Point(DX8[4], DY8[4]), Point(DX8[5], DY8[5]),
                         Point(DX8[6], DY8[6]), Point(DX8[7], DY8[7])};
constexpr Point DP9[] = {Point(DX9[0], DY9[0]), Point(DX9[1], DY9[1]),
                         Point(DX9[2], DY9[2]), Point(DX9[3], DY9[3]),
                         Point(DX9[4], DY9[4]), Point(DX9[5], DY9[5]),
                         Point(DX9[6], DY9[6]), Point(DX9[7], DY9[7])};

// 文字列の先頭の0を削除する
string cutZeroLeft(const string &str) {
  for (int i = 0; i < (int)str.length(); ++i) {
    if (str[i] != '0') {
      return str.substr(i);
    }
  }
  return "";
}

// 0以上の整数を0埋めで表記する
string fillZero(ull number, int digit) {
  int zeroNum = max(0, (int)(digit - to_string(number).length()));
  return move(move(string(zeroNum, '0')) + move(to_string(number)));
}

// 0以上の10進数を2進数に変換する
string toBinString(ull x) {
  return move(cutZeroLeft(bitset<20>(x).to_string()));
}

// 0以上の10進数を8進数に変換する
string toOctString(ull x) {
  stringstream ss;
  ss << std::oct << x;
  return move(ss.str());
}

// 0以上の整数を16進数に変換する(a～fは小文字)
string toHexString(ull x) {
  stringstream ss;
  ss << std::hex << x;
  return move(ss.str());
}

// 0以上の整数を任意の基数に変換する(最大36進数)(a～zは小文字)
string toBaseString(ull x, int base) {
  const string table = "0123456789abcdefghijklmnopqrstuvwxyz";

  assert(base >= 2 && base <= 36);

  string result = "";
  ull y = x;
  do {
    ull div = y / (ull)base;
    int mod = y % (ull)base;

    result = table[mod] + result;
    y = div;
  } while (y != 0ull);

  return move(result);
}

// 任意の基数の0以上の整数を10進数に変換する
// base: 変換元の基数
ull toDecimal(string numberString, int base) {
  assert(numberString.length() < 20);
  assert(!numberString.empty());
  return stoull(numberString, nullptr, base);
}

// double型の値を任意の少数桁数で表示する
// 指定の桁数まで0で埋める。指数表記にはならない
// precision=0を指定したときは小数点は表示しない
// 表示桁数＋１桁目を四捨五入する
string sprintDoublePlane(double value, int precision) {
  assert(precision >= 0);
  stringstream ss;
  ss << fixed << setprecision(precision) << value;
  return move(ss.str());
}

template <typename A> void in(A &a) {
  cin >> a;
  cin.ignore();
}
template <typename A, typename B> void in(A &a, B &b) {
  cin >> a >> b;
  cin.ignore();
}
template <typename A, typename B, typename C> void in(A &a, B &b, C &c) {
  cin >> a >> b >> c;
  cin.ignore();
}
template <typename A, typename B, typename C, typename D>
void in(A &a, B &b, C &c, D &d) {
  cin >> a >> b >> c >> d;
  cin.ignore();
}
template <typename A, typename B, typename C, typename D, typename E>
void in(A &a, B &b, C &c, D &d, E &e) {
  cin >> a >> b >> c >> d >> e;
  cin.ignore();
}
template <typename A, typename B, typename C, typename D, typename E,
          typename F>
void in(A &a, B &b, C &c, D &d, E &e, F &f) {
  cin >> a >> b >> c >> d >> e >> f;
  cin.ignore();
}
template <typename A, typename B, typename C, typename D, typename E,
          typename F, typename G>
void in(A &a, B &b, C &c, D &d, E &e, F &f, G &g) {
  cin >> a >> b >> c >> d >> e >> f >> g;
  cin.ignore();
}

template <typename A> void inr(vector<A> &a, int size) {
  resize(a, size);
  for (int i = 0; i < size; ++i) {
    cin >> a[i];
    cin.ignore();
  }
}
template <typename A, typename B>
void inr(vector<A> &a, vector<B> &b, int size) {
  resize(a, size);
  resize(b, size);
  for (int i = 0; i < size; ++i) {
    cin >> a[i] >> b[i];
    cin.ignore();
  }
}
template <typename A, typename B, typename C>
void inr(vector<A> &a, vector<B> &b, vector<C> &c, int size) {
  resize(a, size);
  resize(b, size);
  resize(c, size);
  for (int i = 0; i < size; ++i) {
    cin >> a[i] >> b[i] >> c[i];
    cin.ignore();
  }
}
template <typename A, typename B, typename C, typename D>
void inr(vector<A> &a, vector<B> &b, vector<C> &c, vector<D> &d, int size) {
  resize(a, size);
  resize(b, size);
  resize(c, size);
  resize(d, size);
  for (int i = 0; i < size; ++i) {
    cin >> a[i] >> b[i] >> c[i] >> d[i];
    cin.ignore();
  }
}
template <typename A, typename B, typename C, typename D, typename E>
void inr(vector<A> &a, vector<B> &b, vector<C> &c, vector<D> &d, vector<E> &e,
         int size) {
  resize(a, size);
  resize(b, size);
  resize(c, size);
  resize(d, size);
  resize(e, size);
  for (int i = 0; i < size; ++i) {
    cin >> a[i] >> b[i] >> c[i] >> d[i] >> e[i];
    cin.ignore();
  }
}

template <typename A> void inr(vector<vector<A>> &a, int h, int wa) {
  resize(a, h, wa);
  for (int i = 0; i < h; ++i) {
    for (int j = 0; j < wa; ++j) {
      cin >> a[i][j];
    }
    cin.ignore();
  }
}
template <typename A, typename B>
void inr(vector<vector<A>> &a, vector<vector<B>> &b, int h, int wa, int wb) {
  resize(a, h, wa);
  resize(b, h, wb);
  for (int i = 0; i < h; ++i) {
    for (int j = 0; j < wa; ++j) {
      cin >> a[i][j];
    }
    for (int j = 0; j < wb; ++j) {
      cin >> b[i][j];
    }
    cin.ignore();
  }
}
template <typename A, typename B, typename C>
void inr(vector<vector<A>> &a, vector<vector<B>> &b, vector<vector<C>> &c,
         int h, int wa, int wb, int wc) {
  resize(a, h, wa);
  resize(b, h, wb);
  resize(c, h, wc);
  for (int i = 0; i < h; ++i) {
    for (int j = 0; j < wa; ++j) {
      cin >> a[i][j];
    }
    for (int j = 0; j < wb; ++j) {
      cin >> b[i][j];
    }
    for (int j = 0; j < wc; ++j) {
      cin >> c[i][j];
    }
    cin.ignore();
  }
}

template <typename T> void out(const T &val) { cout << val << endl; }

static constexpr int COMBI_MAX = 500000; // nCrのnとrの最大値
static ull gFact[COMBI_MAX + 1];         // modの世界での階乗
static ull gInv[COMBI_MAX + 1];          // modの世界での逆元
static ull gFactInv[COMBI_MAX + 1];      // modの世界での逆元の階乗
static ull gCombiInitMod = 0; // 組み合わせの計算に使用したmod値

// 組み合わせテーブルを作る
static void initCombination(ull mod) {
  gFact[0] = gFact[1] = 1;
  gFactInv[0] = gFactInv[1] = 1;
  gInv[1] = 1;
  for (int i = 2; i <= COMBI_MAX; i++) {
    gFact[i] = gFact[i - 1] * i % mod;
    gInv[i] = mod - gInv[mod % i] * (mod / i) % mod;
    gFactInv[i] = gFactInv[i - 1] * gInv[i] % mod;
  }
  gCombiInitMod = mod;
}
static void initCombination() { initCombination(V_MOD); }

// 組み合わせの数を計算
static long long combination(ull n, ull k) {
  assert(gCombiInitMod > 0 && "先にinitCombinationを呼び出して");
  assert(n <= (ull)COMBI_MAX);
  assert(k <= (ull)COMBI_MAX);
  if (n < k)
    return 0;
  return (gFact[n] * ((gFactInv[k] * gFactInv[n - k]) % V_MOD)) % V_MOD;
}
} // namespace ValLib

using namespace ValLib;

int H, W, K;
vector<vector<char>> c;
vector<vector<int>> a;

int solve(int val, bool &success) {

  vector<int> indexes(H, 0);
  int count = 0;
  for (int i = 0; i < H; ++i) {
    indexes[i] = count;
    if ((val & (1 << i)) != 0) {
      ++count;
    }
  }
  ++count;

  int cut = 0;
  vector<int> sums(H, 0);
  for (int x = 0; x < W; ++x) {
    vector<int> lineSum(indexes.size(), 0);
    for (int y = 0; y < H; ++y) {
      lineSum[indexes[y]] += a[y][x];
    }
    for (int y = 0; y < H; ++y) {
      if (lineSum[indexes[y]] > K) {
        success = false;
        return 0;
      }
    }
    for (int i = 0; i < count; ++i) {
      sums[i] += lineSum[i];
    }
    bool cutFlg = false;
    for (int y = 0; y < H; ++y) {
      if (sums[indexes[y]] > K) {
        cutFlg = true;
        break;
      }
    }
    if (cutFlg) {
      ++cut;
      for (int y = 0; y < H; ++y) {
        sums[indexes[y]] = lineSum[indexes[y]];
      }
    }
  }
  success = true;
  return cut;
}

int main() {

  in(H, W, K);
  c.resize(H);
  for (int y = 0; y < H; ++y) {
    c[y].resize(W);
    string line;
    getline(cin, line);
    for (int x = 0; x < W; ++x) {
      c[y][x] = line[x];
    }
  }
  a.resize(H, vector<int>(W, 0));
  for (int y = 0; y < H; ++y) {
    for (int x = 0; x < W; ++x) {
      if (c[y][x] == '1') {
        a[y][x] = 1;
      } else {
        a[y][x] = 0;
      }
    }
  }

  int sum = 0;
  for (int y = 0; y < H; ++y) {
    for (int x = 0; x < W; ++x) {
      sum += a[y][x];
    }
  }
  if (sum <= K) {
    out(0);
  } else {

    int loopNum = 1;
    for (int i = 0; i < H; ++i) {
      loopNum *= 2;
    }
    int minNum = 99999999;
    for (int i = 0; i < loopNum; ++i) {
      bool success = false;
      int num = solve(i, success);
      for (int j = 0; j < H; ++j) {
        if (((1 << j) & i) != 0) {
          ++num;
        }
      }
      if (success && num < minNum) {
        minNum = num;
      }
    }

    out(minNum);
  }
}


Fixed submission:
// #define NDEBUG

#pragma GCC optimize("O3") // 最適化レベルの変更 O0〜O3 などを指定
#pragma GCC optimize("-O3,inline,omit-frame-pointer,unroll-loops")
#pragma warning(1 : 4456) // 多重forループ内での変数の２重定義を警告にする

#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES

#include <iostream>

#include <algorithm>
#include <array>
#include <bitset>
#include <cmath>
#include <fstream>
#include <iomanip>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <cassert>
#include <memory>

#include <chrono>
#include <functional>

using namespace std;

namespace ValLib {

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;

constexpr ull V_MOD = 1000000007ull;
constexpr int V_INT_MAX = 2147483647;
constexpr ll V_LL_MAX = 9223372036854775807ll;
constexpr ull V_ULL_MAX = 18446744073709551615ull;

template <typename Key, typename Value>
using umap = std::unordered_map<Key, Value>;
template <typename T> using uset = std::unordered_set<T>;

template <typename T> void fill(vector<T> &vec, const T &value) {
  std::fill(vec.begin(), vec.end(), value);
}
template <typename T> void fill(vector<vector<T>> &vec, const T &value) {
  for (vector<T> &t : vec)
    std::fill(t.begin(), t.end(), value);
}
template <typename T> void resize(vector<T> &vec, int size1) {
  vec.resize(size1);
}
template <typename T> void resize(vector<T> &vec, int size1, const T &value) {
  vec.resize(size1, value);
}
template <typename T>
void resize(vector<vector<T>> &vec, int size1, int size2) {
  vec.resize(size1);
  for (vector<T> &t : vec)
    t.resize(size2);
}
template <typename T>
void resize(vector<vector<T>> &vec, int size1, int size2, const T &value) {
  vec.resize(size1);
  for (vector<T> &t : vec)
    t.resize(size2, value);
}
template <typename T> void assign(vector<T> &vec, int size1, const T &value) {
  vec.assign(size1, value);
}
template <typename T>
void assign(vector<vector<T>> &vec, int size1, int size2, const T &value) {
  vec.resize(size1);
  for (vector<T> &t : vec)
    t.assign(size2, value);
}
template <typename T>
const typename vector<T>::const_iterator max_element(const vector<T> &vec) {
  assert(!vec.empty());
  return std::max_element(vec.begin(), vec.end());
}
template <typename T, typename _Pr>
const typename vector<T>::const_iterator max_element(const vector<T> &vec,
                                                     _Pr lessThan) {
  assert(!vec.empty());
  return std::max_element(vec.begin(), vec.end(), lessThan);
}
template <typename T> typename vector<T>::iterator min_element(vector<T> &vec) {
  assert(!vec.empty());
  return std::min_element(vec.begin(), vec.end());
}
template <typename T>
const typename vector<T>::const_iterator min_element(const vector<T> &vec) {
  assert(!vec.empty());
  return std::min_element(vec.begin(), vec.end());
}
template <typename T, typename _Pr>
const typename vector<T>::const_iterator min_element(const vector<T> &vec,
                                                     _Pr lessThan) {
  assert(!vec.empty());
  return std::min_element(vec.begin(), vec.end(), lessThan);
}
int accumulate(const vector<int> &vec) {
  return std::accumulate(vec.begin(), vec.end(), 0);
}
template <typename _Pr> int accumulate(const vector<int> &vec, _Pr func) {
  return std::accumulate(vec.begin(), vec.end(), 0, func);
}
double accumulate(const vector<double> &vec) {
  return std::accumulate(vec.begin(), vec.end(), 0.0);
}
template <typename _Pr> double accumulate(const vector<double> &vec, _Pr func) {
  return std::accumulate(vec.begin(), vec.end(), 0.0, func);
}
float accumulate(const vector<float> &vec) {
  return std::accumulate(vec.begin(), vec.end(), 0.f);
}
template <typename _Pr> float accumulate(const vector<float> &vec, _Pr func) {
  return std::accumulate(vec.begin(), vec.end(), 0.f, func);
}
template <typename T, typename _Pr>
bool all_of(const vector<T> &vec, _Pr pred) {
  return std::all_of(vec.begin(), vec.end(), pred);
}
template <typename T, typename _Pr>
bool any_of(const vector<T> &vec, _Pr pred) {
  return std::any_of(vec.begin(), vec.end(), pred);
}
template <typename T, typename _Pr>
bool none_of(const vector<T> &vec, _Pr pred) {
  return std::none_of(vec.begin(), vec.end(), pred);
}
template <typename T>
const typename vector<T>::const_iterator find(const vector<T> &vec,
                                              const T &val) {
  return std::find(vec.begin(), vec.end(), val);
}
template <typename T, typename _Pr>
const typename vector<T>::const_iterator find_if(const vector<T> &vec,
                                                 _Pr pred) {
  return std::find_if(vec.begin(), vec.end(), pred);
}
template <typename T> bool contains(const vector<T> &vec, const T &val) {
  return std::find(vec.begin(), vec.end(), val) != vec.end();
}
template <typename T, typename _Pr>
bool contains_if(const vector<T> &vec, _Pr pred) {
  return std::find_if(vec.begin(), vec.end(), pred) != vec.end();
}
template <typename T, typename _Pr>
typename iterator_traits<
    const typename vector<T>::const_iterator>::difference_type
count_if(const vector<T> &vec, _Pr pred) {
  return std::count_if(vec.begin(), vec.end(), pred);
}
template <typename T> void sort(vector<T> &vec) {
  std::sort(vec.begin(), vec.end());
}
template <typename T, typename _Pr> void sort(vector<T> &vec, _Pr pred) {
  std::sort(vec.begin(), vec.end(), pred);
}
template <typename T> void stable_sort(vector<T> &vec) {
  std::stable_sort(vec.begin(), vec.end());
}
template <typename T, typename _Pr> void stable_sort(vector<T> &vec, _Pr pred) {
  std::stable_sort(vec.begin(), vec.end(), pred);
}

template <typename T, size_t N> void fill(array<T, N> &ary, const T &value) {
  std::fill(ary.begin(), ary.end(), value);
}
template <typename T, size_t N, size_t M>
void fill(array<array<T, M>, N> &ary, const T &value) {
  for (array<T, M> &t : ary)
    std::fill(t.begin(), t.end(), value);
}
template <typename T, size_t N, typename _Pr>
const typename array<T, N>::const_iterator max_element(const array<T, N> &ary) {
  assert(!ary.empty());
  return std::max_element(ary.begin(), ary.end());
}
template <typename T, size_t N, typename _Pr>
const typename vector<T>::const_iterator max_element(const array<T, N> &ary) {
  assert(!ary.empty());
  return std::max_element(ary.begin(), ary.end());
}
template <typename T, size_t N, typename _Pr>
const typename array<T, N>::const_iterator max_element(const array<T, N> &ary,
                                                       _Pr lessThan) {
  assert(!ary.empty());
  return std::max_element(ary.begin(), ary.end(), lessThan);
}
template <typename T, size_t N, typename _Pr>
const typename array<T, N>::const_iterator min_element(const array<T, N> &ary) {
  assert(!ary.empty());
  return std::min_element(ary.begin(), ary.end());
}
template <typename T, size_t N, typename _Pr>
const typename array<T, N>::const_iterator min_element(const array<T, N> &ary,
                                                       _Pr lessThan) {
  assert(!ary.empty());
  return std::min_element(ary.begin(), ary.end(), lessThan);
}
template <size_t N> int accumulate(const array<int, N> &ary) {
  return std::accumulate(ary.begin(), ary.end(), 0);
}
template <size_t N, typename _Pr>
int accumulate(const array<int, N> &ary, _Pr func) {
  return std::accumulate(ary.begin(), ary.end(), 0, func);
}
template <size_t N> double accumulate(const array<double, N> &ary) {
  return std::accumulate(ary.begin(), ary.end(), 0.0);
}
template <size_t N, typename _Pr>
double accumulate(const array<double, N> &ary, _Pr func) {
  return std::accumulate(ary.begin(), ary.end(), 0.0, func);
}
template <size_t N> float accumulate(const array<float, N> &ary) {
  return std::accumulate(ary.begin(), ary.end(), 0.f);
}
template <size_t N, typename _Pr>
float accumulate(const array<float, N> &ary, _Pr func) {
  return std::accumulate(ary.begin(), ary.end(), 0.f, func);
}
template <typename T, size_t N, typename _Pr>
bool all_of(const array<T, N> &ary, _Pr pred) {
  return std::all_of(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N, typename _Pr>
bool any_of(const array<T, N> &ary, _Pr pred) {
  return std::any_of(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N, typename _Pr>
bool none_of(const array<T, N> &ary, _Pr pred) {
  return std::none_of(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N>
const typename array<T, N>::const_iterator find(const array<T, N> &ary,
                                                const T &val) {
  return std::find(ary.begin(), ary.end(), val);
}
template <typename T, size_t N, typename _Pr>
const typename array<T, N>::const_iterator find_if(const array<T, N> &ary,
                                                   _Pr pred) {
  return std::find_if(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N>
bool contains(const array<T, N> &ary, const T &val) {
  return std::find(ary.begin(), ary.end(), val) != ary.end();
}
template <typename T, size_t N, typename _Pr>
bool contains_if(const array<T, N> &ary, _Pr pred) {
  return std::find_if(ary.begin(), ary.end(), pred) != ary.end();
}
template <typename T, size_t N, typename _Pr>
typename iterator_traits<
    const typename array<T, N>::const_iterator>::difference_type
count_if(const array<T, N> &ary, _Pr pred) {
  return std::count_if(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N> void sort(array<T, N> &ary) {
  std::sort(ary.begin(), ary.end());
}
template <typename T, size_t N, typename _Pr>
void sort(array<T, N> &ary, _Pr pred) {
  std::sort(ary.begin(), ary.end(), pred);
}
template <typename T, size_t N> void stable_sort(array<T, N> &ary) {
  std::stable_sort(ary.begin(), ary.end());
}
template <typename T, size_t N, typename _Pr>
void stable_sort(array<T, N> &ary, _Pr pred) {
  std::stable_sort(ary.begin(), ary.end(), pred);
}

template <typename Key, typename Value>
bool containsKey(const umap<Key, Value> &m, const Key &key) {
  return m.find(key) != m.end();
}
template <typename Key, typename Value>
bool containsValue(const umap<Key, Value> &m, const Value &val) {
  for (auto it = m.begin(); it != m.end(); ++it)
    if (it->second == val)
      return true;
  return false;
}
template <typename T>
const typename uset<T>::const_iterator find(const uset<T> &s, const T &key) {
  return s.find(key);
}
template <typename T> bool contains(const uset<T> &s, const T &key) {
  return s.find(key) != s.end();
}

constexpr int DX4[] = {0, -1, 0, 1};
constexpr int DY4[] = {-1, 0, 1, 0};
constexpr int DX8[] = {0, -1, -1, -1, 0, 1, 1, 1};
constexpr int DY8[] = {-1, -1, 0, 1, 1, 1, 0, -1};

constexpr int DX5[] = {DX4[0], DX4[1], DX4[2], DX4[3], 0};
constexpr int DY5[] = {DY4[0], DY4[1], DY4[2], DY4[3], 0};
constexpr int DX9[] = {DX8[0], DX8[1], DX8[2], DX8[3], DX8[4],
                       DX8[5], DX8[6], DX8[7], 0};
constexpr int DY9[] = {DY8[0], DY8[1], DY8[2], DY8[3], DY8[4],
                       DY8[5], DY8[6], DY8[7], 0};

class Point {
public:
  constexpr inline Point() : Point(-1, -1) {}
  constexpr inline Point(int x, int y) : x(x), y(y) {}

  static Point getManhattanDist(const Point &p1, const Point &p2) {
    return move(Point(abs(p1.x - p2.x), abs(p1.y - p2.y)));
  }

  void setPos(const Point &pos) {
    x = pos.x;
    y = pos.y;
  }
  void setPos(int x, int y) {
    this->x = x;
    this->y = y;
  }

  Point operator+(int val) const { return move(Point(x + val, y + val)); }
  Point operator-(int val) const { return move(Point(x - val, y - val)); }
  Point operator*(int val) const { return move(Point(x * val, y * val)); }
  Point operator/(int val) const { return move(Point(x / val, y / val)); }
  Point operator+(const Point &p) const {
    return move(Point(x + p.x, y + p.y));
  }
  Point operator-(const Point &p) const {
    return move(Point(x - p.x, y - p.y));
  }
  Point operator*(const Point &p) const {
    return move(Point(x * p.x, y * p.y));
  }
  Point operator/(const Point &p) const {
    return move(Point(x / p.x, y / p.y));
  }
  void operator+=(int val) {
    x += val;
    y += val;
  }
  void operator-=(int val) {
    x -= val;
    y -= val;
  }
  void operator*=(int val) {
    x *= val;
    y *= val;
  }
  void operator/=(int val) {
    x /= val;
    y /= val;
  }
  void operator+=(const Point &p) {
    x += p.x;
    y += p.y;
  }
  void operator-=(const Point &p) {
    x -= p.x;
    y -= p.y;
  }
  void operator*=(const Point &p) {
    x *= p.x;
    y *= p.y;
  }
  void operator/=(const Point &p) {
    x /= p.x;
    y /= p.y;
  }
  bool operator==(const Point &p) const { return x == p.x && y == p.y; }
  bool operator!=(const Point &p) const { return x != p.x || y != p.y; }
  // bool operator<(const Point &p) const {return x * x + y * y < p.x * p.x +
  // p.y * p.y;}
  const Point &getPos() const { return *this; }

  string to_string() const {
    return "(" + std::to_string(x) + ", " + std::to_string(y) + ")";
  }

  int x, y;
};

constexpr Point DP4[] = {Point(DX4[0], DY4[0]), Point(DX4[1], DY4[1]),
                         Point(DX4[2], DY4[2]), Point(DX4[3], DY4[3])};
constexpr Point DP5[] = {Point(DX5[0], DY5[0]), Point(DX5[1], DY5[1]),
                         Point(DX5[2], DY5[2]), Point(DX5[3], DY5[3]),
                         Point(DX5[4], DY5[4])};
constexpr Point DP8[] = {Point(DX8[0], DY8[0]), Point(DX8[1], DY8[1]),
                         Point(DX8[2], DY8[2]), Point(DX8[3], DY8[3]),
                         Point(DX8[4], DY8[4]), Point(DX8[5], DY8[5]),
                         Point(DX8[6], DY8[6]), Point(DX8[7], DY8[7])};
constexpr Point DP9[] = {Point(DX9[0], DY9[0]), Point(DX9[1], DY9[1]),
                         Point(DX9[2], DY9[2]), Point(DX9[3], DY9[3]),
                         Point(DX9[4], DY9[4]), Point(DX9[5], DY9[5]),
                         Point(DX9[6], DY9[6]), Point(DX9[7], DY9[7])};

// 文字列の先頭の0を削除する
string cutZeroLeft(const string &str) {
  for (int i = 0; i < (int)str.length(); ++i) {
    if (str[i] != '0') {
      return str.substr(i);
    }
  }
  return "";
}

// 0以上の整数を0埋めで表記する
string fillZero(ull number, int digit) {
  int zeroNum = max(0, (int)(digit - to_string(number).length()));
  return move(move(string(zeroNum, '0')) + move(to_string(number)));
}

// 0以上の10進数を2進数に変換する
string toBinString(ull x) {
  return move(cutZeroLeft(bitset<20>(x).to_string()));
}

// 0以上の10進数を8進数に変換する
string toOctString(ull x) {
  stringstream ss;
  ss << std::oct << x;
  return move(ss.str());
}

// 0以上の整数を16進数に変換する(a～fは小文字)
string toHexString(ull x) {
  stringstream ss;
  ss << std::hex << x;
  return move(ss.str());
}

// 0以上の整数を任意の基数に変換する(最大36進数)(a～zは小文字)
string toBaseString(ull x, int base) {
  const string table = "0123456789abcdefghijklmnopqrstuvwxyz";

  assert(base >= 2 && base <= 36);

  string result = "";
  ull y = x;
  do {
    ull div = y / (ull)base;
    int mod = y % (ull)base;

    result = table[mod] + result;
    y = div;
  } while (y != 0ull);

  return move(result);
}

// 任意の基数の0以上の整数を10進数に変換する
// base: 変換元の基数
ull toDecimal(string numberString, int base) {
  assert(numberString.length() < 20);
  assert(!numberString.empty());
  return stoull(numberString, nullptr, base);
}

// double型の値を任意の少数桁数で表示する
// 指定の桁数まで0で埋める。指数表記にはならない
// precision=0を指定したときは小数点は表示しない
// 表示桁数＋１桁目を四捨五入する
string sprintDoublePlane(double value, int precision) {
  assert(precision >= 0);
  stringstream ss;
  ss << fixed << setprecision(precision) << value;
  return move(ss.str());
}

template <typename A> void in(A &a) {
  cin >> a;
  cin.ignore();
}
template <typename A, typename B> void in(A &a, B &b) {
  cin >> a >> b;
  cin.ignore();
}
template <typename A, typename B, typename C> void in(A &a, B &b, C &c) {
  cin >> a >> b >> c;
  cin.ignore();
}
template <typename A, typename B, typename C, typename D>
void in(A &a, B &b, C &c, D &d) {
  cin >> a >> b >> c >> d;
  cin.ignore();
}
template <typename A, typename B, typename C, typename D, typename E>
void in(A &a, B &b, C &c, D &d, E &e) {
  cin >> a >> b >> c >> d >> e;
  cin.ignore();
}
template <typename A, typename B, typename C, typename D, typename E,
          typename F>
void in(A &a, B &b, C &c, D &d, E &e, F &f) {
  cin >> a >> b >> c >> d >> e >> f;
  cin.ignore();
}
template <typename A, typename B, typename C, typename D, typename E,
          typename F, typename G>
void in(A &a, B &b, C &c, D &d, E &e, F &f, G &g) {
  cin >> a >> b >> c >> d >> e >> f >> g;
  cin.ignore();
}

template <typename A> void inr(vector<A> &a, int size) {
  resize(a, size);
  for (int i = 0; i < size; ++i) {
    cin >> a[i];
    cin.ignore();
  }
}
template <typename A, typename B>
void inr(vector<A> &a, vector<B> &b, int size) {
  resize(a, size);
  resize(b, size);
  for (int i = 0; i < size; ++i) {
    cin >> a[i] >> b[i];
    cin.ignore();
  }
}
template <typename A, typename B, typename C>
void inr(vector<A> &a, vector<B> &b, vector<C> &c, int size) {
  resize(a, size);
  resize(b, size);
  resize(c, size);
  for (int i = 0; i < size; ++i) {
    cin >> a[i] >> b[i] >> c[i];
    cin.ignore();
  }
}
template <typename A, typename B, typename C, typename D>
void inr(vector<A> &a, vector<B> &b, vector<C> &c, vector<D> &d, int size) {
  resize(a, size);
  resize(b, size);
  resize(c, size);
  resize(d, size);
  for (int i = 0; i < size; ++i) {
    cin >> a[i] >> b[i] >> c[i] >> d[i];
    cin.ignore();
  }
}
template <typename A, typename B, typename C, typename D, typename E>
void inr(vector<A> &a, vector<B> &b, vector<C> &c, vector<D> &d, vector<E> &e,
         int size) {
  resize(a, size);
  resize(b, size);
  resize(c, size);
  resize(d, size);
  resize(e, size);
  for (int i = 0; i < size; ++i) {
    cin >> a[i] >> b[i] >> c[i] >> d[i] >> e[i];
    cin.ignore();
  }
}

template <typename A> void inr(vector<vector<A>> &a, int h, int wa) {
  resize(a, h, wa);
  for (int i = 0; i < h; ++i) {
    for (int j = 0; j < wa; ++j) {
      cin >> a[i][j];
    }
    cin.ignore();
  }
}
template <typename A, typename B>
void inr(vector<vector<A>> &a, vector<vector<B>> &b, int h, int wa, int wb) {
  resize(a, h, wa);
  resize(b, h, wb);
  for (int i = 0; i < h; ++i) {
    for (int j = 0; j < wa; ++j) {
      cin >> a[i][j];
    }
    for (int j = 0; j < wb; ++j) {
      cin >> b[i][j];
    }
    cin.ignore();
  }
}
template <typename A, typename B, typename C>
void inr(vector<vector<A>> &a, vector<vector<B>> &b, vector<vector<C>> &c,
         int h, int wa, int wb, int wc) {
  resize(a, h, wa);
  resize(b, h, wb);
  resize(c, h, wc);
  for (int i = 0; i < h; ++i) {
    for (int j = 0; j < wa; ++j) {
      cin >> a[i][j];
    }
    for (int j = 0; j < wb; ++j) {
      cin >> b[i][j];
    }
    for (int j = 0; j < wc; ++j) {
      cin >> c[i][j];
    }
    cin.ignore();
  }
}

template <typename T> void out(const T &val) { cout << val << endl; }

static constexpr int COMBI_MAX = 500000; // nCrのnとrの最大値
static ull gFact[COMBI_MAX + 1];         // modの世界での階乗
static ull gInv[COMBI_MAX + 1];          // modの世界での逆元
static ull gFactInv[COMBI_MAX + 1];      // modの世界での逆元の階乗
static ull gCombiInitMod = 0; // 組み合わせの計算に使用したmod値

// 組み合わせテーブルを作る
static void initCombination(ull mod) {
  gFact[0] = gFact[1] = 1;
  gFactInv[0] = gFactInv[1] = 1;
  gInv[1] = 1;
  for (int i = 2; i <= COMBI_MAX; i++) {
    gFact[i] = gFact[i - 1] * i % mod;
    gInv[i] = mod - gInv[mod % i] * (mod / i) % mod;
    gFactInv[i] = gFactInv[i - 1] * gInv[i] % mod;
  }
  gCombiInitMod = mod;
}
static void initCombination() { initCombination(V_MOD); }

// 組み合わせの数を計算
static long long combination(ull n, ull k) {
  assert(gCombiInitMod > 0 && "先にinitCombinationを呼び出して");
  assert(n <= (ull)COMBI_MAX);
  assert(k <= (ull)COMBI_MAX);
  if (n < k)
    return 0;
  return (gFact[n] * ((gFactInv[k] * gFactInv[n - k]) % V_MOD)) % V_MOD;
}
} // namespace ValLib

using namespace ValLib;

int H, W, K;
vector<vector<char>> c;
vector<vector<int>> a;

int solve(int val, bool &success) {

  vector<int> indexes(H, 0);
  int count = 0;
  for (int i = 0; i < H; ++i) {
    indexes[i] = count;
    if ((val & (1 << i)) != 0) {
      ++count;
    }
  }
  ++count;

  int cut = 0;
  vector<int> sums(H, 0);
  for (int x = 0; x < W; ++x) {
    vector<int> lineSum(indexes.size(), 0);
    for (int y = 0; y < H; ++y) {
      lineSum[indexes[y]] += a[y][x];
    }
    for (int y = 0; y < H; ++y) {
      if (lineSum[indexes[y]] > K) {
        success = false;
        return 0;
      }
    }
    for (int i = 0; i < H; ++i) {
      sums[i] += lineSum[i];
    }
    bool cutFlg = false;
    for (int y = 0; y < H; ++y) {
      if (sums[indexes[y]] > K) {
        cutFlg = true;
        break;
      }
    }
    if (cutFlg) {
      ++cut;
      for (int y = 0; y < H; ++y) {
        sums[indexes[y]] = lineSum[indexes[y]];
      }
    }
  }
  success = true;
  return cut;
}

int main() {

  in(H, W, K);
  c.resize(H);
  for (int y = 0; y < H; ++y) {
    c[y].resize(W);
    string line;
    getline(cin, line);
    for (int x = 0; x < W; ++x) {
      c[y][x] = line[x];
    }
  }
  a.resize(H, vector<int>(W, 0));
  for (int y = 0; y < H; ++y) {
    for (int x = 0; x < W; ++x) {
      if (c[y][x] == '1') {
        a[y][x] = 1;
      } else {
        a[y][x] = 0;
      }
    }
  }

  int sum = 0;
  for (int y = 0; y < H; ++y) {
    for (int x = 0; x < W; ++x) {
      sum += a[y][x];
    }
  }
  if (sum <= K) {
    out(0);
  } else {

    int loopNum = 1;
    for (int i = 0; i < H; ++i) {
      loopNum *= 2;
    }
    int minNum = 99999999;
    for (int i = 0; i < loopNum; ++i) {
      bool success = false;
      int num = solve(i, success);
      for (int j = 0; j < H; ++j) {
        if (((1 << j) & i) != 0) {
          ++num;
        }
      }
      if (success && num < minNum) {
        minNum = num;
      }
    }

    out(minNum);
  }
}