#include #include #include #include #include #include #include #include constexpr int32_t INF = std::numeric_limits::max() / 4; int main() { int32_t m, n; std::cin >> m >> n; std::vector matrix(m); for (auto& row : matrix) { std::cin >> row; } if (m < n) { // transpose std::vector flip(n); for (auto i = 0; i < n; ++i) { flip[i].assign(m, '0'); for (auto j = 0; j < m; ++j) { flip[i][j] = matrix[j][i]; } } matrix = std::move(flip); std::swap(m, n); } assert(m >= n); std::vector> dp(n, std::vector(n, INF)); std::vector psum(n + 1, 0); for (auto i = 0; i < m; ++i) { for (auto j = 0; j < n; ++j) { psum[j + 1] = psum[j] + (matrix[i][j] - '0'); } std::vector prevDp = dp[0]; std::vector> ndp(n, std::vector(n, INF)); for (auto l = 0; l < n; ++l) { for (auto r = 0; r < n; ++r) { prevDp[r] = std::min(prevDp[r], dp[l][r]); } int32_t bestDp = prevDp[l == 0 ? 0 : l - 1]; for (auto r = l; r < n; ++r) { // min cost to make this row's band [l, r] int32_t zeroLeft = psum[l]; int32_t oneRange = (r - l + 1) - (psum[r + 1] - psum[l]); int32_t zeroRight = psum[n] - psum[r + 1]; bestDp = std::min(bestDp, prevDp[r]); ndp[l][r] = std::min(ndp[l][r], zeroLeft + oneRange + zeroRight + bestDp); } } dp = std::move(ndp); } int32_t ans = INF; for (auto l = 0; l < n; ++l) { ans = std::min(ans, dp[l][n - 1]); } std::cout << ans << '\n'; return 0; }