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 }

原文地址:https://www.cnblogs.com/MingSD/p/8534301.html

时间: 2024-10-01 15:25:21

CodeForces 946D Timetable的相关文章

Codeforces 946D Timetable(预处理+分组背包)

题目链接:http://codeforces.com/problemset/problem/946/D 题目大意:有n个字符串,代表n天的课表,1表示这个时间要上课,0表示不要上课,一天在学校时间为第一节课到最后一节课的时间.总共,可以逃过k次课,求至少需要在学校多少时间. 解题思路:听了大佬说背包,然后预处理就想了20多分钟,比赛结束,GG...先是预处理出v[i][k]即第i天逃k节课的能节约的最多时间,至于怎么求,直接枚举k,然后枚举两端1的位置即可.然后就可以做分组背包了,这就不说了,很

Timetable CodeForces - 946D (预处理+背包)

题意:n天m节课,最多可以逃k节课,每天在学校待的时间为该天上的第一节课到最后一节课持续的时间.问怎样逃课可以使这n天在学校待的时间最短,输出最短的时间. 分析: 1.预处理出每天逃j节课时在学校待的最短时间.t[i][j] 2.dp[i][j]为截止到第i天逃j节课待在学校的最短时间. #include<bits/stdc++.h> using namespace std; const int MAXN = 500 + 10; const int INF = 0x3f3f3f3f; char

Timetable CodeForces - 946D (区间dp)

大意: n天, 每天m小时, 给定课程表, 每天的上课时间为第一个1到最后一个1, 一共可以逃k次课, 求最少上课时间. 每天显然是独立的, 对每天区间dp出逃$x$次课的最大减少时间, 再对$n$天dp即可. #include <iostream> #include <sstream> #include <algorithm> #include <cstdio> #include <math.h> #include <set> #i

Codeforces 1039A. Timetable

题目地址:http://codeforces.com/problemset/problem/1039/A 题目的关键在于理清楚思路,然后代码就比较容易写了 对于每一个位置的bus,即对于每一个i(i>=1 && i<=n) ,x[i]必然大于等于 i ,假设第 i 个车可以停在 x[i] 处,则对于j(j>i && j<=x[i]) 令车j停在j-1处,即b[j-1]>=ar[j]+t 如果x[x[i]]==x[i],只需控制让b[x[i]]&

946D. Timetable

传送门 预处理加分组背包 n行m列,每列的花费是第一个与最后一个1的构成的区间长度,已知可以去除不多于k个1,求最小花费 #include <map> #include <cstdio> #include <cstring> #include <algorithm> #define INF 0x3f3f3f3f using namespace std; const int maxn = 1e6 + 10; int n, m, k; int A[510]; i

cf946d 怎样逃最多的课dp

来源:codeforces                                              D. Timetable Ivan is a student at Berland State University (BSU). There are n days in Berland week, and each of these days Ivan might have some classes at the university. There are m working

#分组背包 Educational Codeforces Round 39 (Rated for Div. 2) D. Timetable

2018-03-11 http://codeforces.com/contest/946/problem/D D. Timetable time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Ivan is a student at Berland State University (BSU). There are n days in

Codeforces 37D Lesson Timetable - 组合数学 - 动态规划

题目传送门 神奇的门I 神奇的门II 题目大意 有$n$组学生要上课2次课,有$m$个教室,编号为$1$到$m$.要确定有多少种不同的安排上课的教室的方案(每组学生都是本质不同的),使得它们满足: 每组学生第一次上课的教室的编号小于等于第二次上课的教室的编号. 第$i$间教室在第一次上课时,恰好有$x_{i}$组学生在场. 第$i$间教室在某次上课时,中间包含的学生组数不能超过$y_{i}$. 输出答案模$10^{9} + 7$. 因为第一次上课恰好有多少人,所以这个方案数是可以直接用组合数,暂

【 BowWow and the Timetable CodeForces - 1204A 】【思维】

题目链接 可以发现 十进制4 对应 二进制100 十进制16 对应 二进制10000 十进制64 对应 二进制1000000 可以发现每多两个零,4的次幂就增加1. 用string读入题目给定的二进制数字,求出其长len,当len为奇数时,第一位为1,后面的位数如果都为0,则输出len,如果有一个不为0,则输出len+1: 当len为偶数时,则输出len.(之所以这样输出是因为题目给定4的次幂是从0开始的) #include<iostream> #include<string> #