题意: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 }