CodeForces 946D Timetable

CodeForces 946D Timetable

Timetable

题意:ivan 是一个学生, 他们当地一周有n天, 每天有m节课,每节课一小时, 然后‘1’代表的是ivan这个时间段需要上课, 现在ivan可以跳过选择K节课不去上, 他在学校的时间为当天他选择的第一节课到当天的最后一节课,也就是可以跳2端的课, 如果当天的没有课, 当天就不需要去学校。现在求这周ivan去学校的时间最小是多少。

题解:算出不逃课的情况下的总时间, 然后用分组背包(因为每天只能有一种情况, 所以只能在每组里面选一种),跑出逃课k节下最多的逃课时间是多少, 总时间-逃课时间就是答案了。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define ULL unsigned LL
 5 #define fi first
 6 #define se second
 7 #define lson l,m,rt<<1
 8 #define rson m+1,r,rt<<1|1
 9 #define max3(a,b,c) max(a,max(b,c))
10 const int INF = 0x3f3f3f3f;
11 const LL mod = 1e9+7;
12 typedef pair<int,int> pll;
13 const int N = 5e3+10;
14 char str[N];
15 int dp[N];
16 int pos[N];
17 int len[N];
18 int n, m, k;
19 int main(){
20     scanf("%d%d%d", &n, &m, &k);
21     int tot = 0;
22     for(int i = 1; i <= n; i++) {
23         scanf("%s", str+1);
24         int cnt = 0;
25         for(int j = 1; j <= m; j++)
26             if(str[j] == '1')
27                 pos[++cnt] = j;
28         if(cnt == 0) continue;
29         memset(len, 0, sizeof(len));
30         int llen = pos[cnt]-pos[1]+1;
31         tot += llen;
32         for(int to = 1; to <= k && to <= cnt; to++){
33                 for(int r = cnt - to, l = 1; r >= l && r <= cnt; r++, l++)
34                     len[to] = max(len[to], llen - (pos[r] - pos[l] + 1));
35                 if(to == cnt)
36                     len[to] = llen;
37             }
38         for(int j = k; j >= 1; j--)
39             for(int to = 1; to <= j && to <= cnt; to++)
40                 dp[j] = max(dp[j], dp[j-to]+len[to]);
41     }
42     printf("%d", tot - dp[k]);
43     return 0;
44 }