预处理一下每一天逃课i天能获得的最大收益 我的预处理好蠢啊 但是不想改了 具体看丑丑的代码TAT
dp_i j表示第i天一共逃j节课所获得的收益
类似背包的转移方程 dp[i][k + j] = max(dp[i][j + k], dp[i - 1][j] + cost[i][k]); // j为之前i - 1天逃课总数 第i天逃k节课
最后再减去一下就行了
写了一晚上 写崩了啊 我好菜
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
using namespace std;
char tu[505][505];
int tot[505];
int pre[505][505];
int cost[505][505];
int dp[505][505];
int main()
{
memset(dp, 0, sizeof(dp));
memset(cost, 0, sizeof(cost));
int n, m, kk;
scanf("%d%d%d", &n, &m, &kk);
int ans = 0;
for(int i = 1; i <= n; i++)
{
scanf("%s", tu[i] + 1);
pre[i][0] = 0;
for(int j = 1; j <= m; j++)
pre[i][j] = pre[i][j - 1] + (tu[i][j] == '1');
tot[i] = pre[i][m];
int l, r;
int summ = 0;
for(int j = 1; j <= m; j++)
if(tu[i][j] == '1')
{
l = j;
break;
}
for(int j = m; j >= 1; j--)
if(tu[i][j] == '1')
{
r = j;
summ = r - l + 1;
break;
}
ans += summ;
for(int j = l; j <= r; j++)
for(int k = j; k <= r; k++)
cost[i][tot[i] - pre[i][k] + pre[i][j - 1]] = max(cost[i][tot[i] - pre[i][k] + pre[i][j - 1]], summ - (k - j + 1));
cost[i][tot[i]] = summ;
}
int sub = 0;
for(int i = 1; i <= tot[1]; i++) dp[1][i] = cost[1][i];
int sum = tot[1];
for(int i = 2; i <= n; i++)
{
sum += tot[i];
for(int j = 0; j <= kk; j++)
for(int k = 0; k + j <= kk; k++)
dp[i][k + j] = max(dp[i][j + k], dp[i - 1][j] + cost[i][k]);
}
if(kk >= sum)
puts("0");
else
printf("%d\n", ans - dp[n][kk]);
return 0;
}