题目链接:https://codeforces.com/problemset/problem/946/D
题目大意:有n周,每周有m个小时。每节课1个小时。1代表有课。0代表没有课。现在可以逃k节课。每一天他都会从第一节课开始。到最后一课结束。问他现在可以逃k次课。让他在学校的时间最少。最小值为多少?

思路:对于第i周。我们可以用v[i][j]表示:第i周逃j节课在学校的最小时间。因为要结果最小。那么这些要上的课肯定是连续的。直接O(n^2)预处理。

每一周为一组。进行分组背包。
f[i][j]:为前i周逃j次课的在学校最小时间。枚举第i周逃k几课进行转移。

#include<bits/stdc++.h>
#define LL long long
using namespace std;

vector<int> a[505];
int v[505][505];//在i周逃j天
int f[2][505];
int main(){

    int n, m, K, x, s1=0;
    scanf("%d%d%d", &n, &m, &K);
    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            scanf("%1d", &x);
            if(x==1){
                a[i].push_back(j);
                s1++;
            }
        }
    }

    if(s1<=K){
        printf("0\n");
        return 0;
    }

    memset(v, 7, sizeof(v));
    for(int i=1; i<=n; i++){

        v[i][a[i].size()]=0;

        for(int j=0; j<a[i].size(); j++){
            for(int k=j; k<a[i].size(); k++){
                v[i][a[i].size()-(k-j+1)]=min(v[i][a[i].size()-(k-j+1)], a[i][k]-a[i][j]+1);
            }
        }
    }

    memset(f, 7, sizeof(f));
    f[0][0]=0;

    int I=0;//滚动数组优化
    for(int i=1; i<=n; i++){
        I^=1;
        memset(f[I], 7, sizeof(f[I]));//记得初始化
        for(int j=K; j>=0; j--){
            for(int k=0; k<=j; k++){
                f[I][j]=min(f[I][j], f[I^1][j-k]+v[i][k]);
            }
        }
    }
    printf("%d\n", f[I][K]);

    return 0;
}