alg2025/src/7/23/T637676d.cpp

103 lines
2.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <cstdint>
#include <iostream>
#include <vector>
#include <algorithm>
using ll = int64_t;
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
ll n, m, k;
cin >> n >> m >> k;
vector<string> v(n);
for (ll i = 0; i < n; i++) {
cin >> v[i];
}
vector<ll> dp(k + 1, 1e9);
dp[0] = 0;
for (ll i = 0; i < n; i++) {
vector<ll> a;
for (ll j = 0; j < m; j++) {
if (v[i][j] == '1') {
a.push_back(j);
}
}
ll p = a.size();
vector<ll> f(p + 1, 0);
if (p == 0) {
vector<ll> ndp = dp;
dp = move(ndp);
continue;
}
f[p] = 0;
for (ll t = 0; t < p; t++) {
ll b = p - 1 - t;
ll mval = 1e9;
for (ll x = 0; x <= t; x++) {
ll cost = a[b + x] - a[x] + 1;
if (cost < mval) {
mval = cost;
}
}
f[t] = mval;
}
vector<ll> ndp(k + 1, 1e9);
for (ll j = 0; j <= k; j++) {
for (ll t = 0; t <= min(p, j); t++) {
if (dp[j - t] != 1e9) {
if (dp[j - t] + f[t] < ndp[j]) {
ndp[j] = dp[j - t] + f[t];
}
}
}
}
dp = move(ndp);
}
ll ans = *min_element(dp.begin(), dp.end());
cout << ans << endl;
return 0;
}
/*
输入处理:
读取矩阵的行数 n、列数 m 和最多可删除的1的数量 k。
读取矩阵的每一行字符串。
动态规划初始化:
初始化 dp 数组,大小为 k+1dp[0] = 0 表示初始状态无删除的代价为0其余初始化为一个大数表示不可达
处理每一行:
收集每行中1的位置索引到数组 a。
如果该行没有1则直接跳过代价为0
否则,计算该行删除 t 个1后的最小代价 f(t)
f[p] = 0 表示删除所有1后代价为0。
对于 0 ≤ t < p计算删除左侧 x 个和右侧 y 个1x + y = t剩余1的第一个和最后一个位置形成的区间长度取最小值作为 f(t)。
更新动态规划状态:
对于当前行,枚举总删除数 j0 到 k枚举当前行删除数 t0 到 min(p, j))。
更新 ndp[j] 为 dp[j - t] + f[t] 的最小值。
输出结果:
最终答案为 dp[0..k] 中的最小值,即所有行在删除不超过 k 个1的情况下的最小总代价。
*/