花了两个晚上来搞这道题。

第一个晚上想思路和写代码,第二个晚上调试。

然而还是菜,一直调不对,我的队友是Debug小能手呀(真的是无敌,哈哈,两个人一会就改好了)

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 Berland week, and each of these days Ivan might have some classes at the university.

There are m working hours during each Berland day, and each lesson at the university lasts exactly one hour. If at some day Ivan's first lesson is during i-th hour, and last lesson is during j-th hour, then he spends j - i + 1 hours in the university during this day. If there are no lessons during some day, then Ivan stays at home and therefore spends 0 hours in the university.

Ivan doesn't like to spend a lot of time in the university, so he has decided to skip some lessons. He cannot skip more than k lessons during the week. After deciding which lessons he should skip and which he should attend, every day Ivan will enter the university right before the start of the first lesson he does not skip, and leave it after the end of the last lesson he decides to attend. If Ivan skips all lessons during some day, he doesn't go to the university that day at all.

Given nmk and Ivan's timetable, can you determine the minimum number of hours he has to spend in the university during one week, if he cannot skip more than k lessons?

Input

The first line contains three integers nm and k (1 ≤ n, m ≤ 500, 0 ≤ k ≤ 500) — the number of days in the Berland week, the number of working hours during each day, and the number of lessons Ivan can skip, respectively.

Then n lines follow, i-th line containing a binary string of m characters. If j-th character in i-th line is 1, then Ivan has a lesson on i-th day during j-th hour (if it is 0, there is no such lesson).

Output

Print the minimum number of hours Ivan has to spend in the university during the week if he skips not more than k lessons.

Examples
input

Copy
  1. 2 5 1
    01001
    10110
output
  1. 5
input

Copy
  1. 2 5 0
    01001
    10110
output
  1. 8
Note

In the first example Ivan can skip any of two lessons during the first day, so he spends 1 hour during the first day and 4 hours during the second day.

In the second example Ivan can't skip any lessons, so he spends 4 hours every day.

这个题的意思就是逃课。怎样逃课才能使得最后上完课的时间减去最开始的上课的时间最短。

这里是按0和1来代表有没有课,1代表有课,可以逃。但是最多只能逃k节课。否则就直接坐飞机了。。。

样例01001如果一节也不逃的话,就是最后一个1的位置减去第一个1的位置的距离。为4。

想思路真的是炸裂。

因为是找最优子结构,所以肯定是用动态规划写,有人说是背包,就发现是分组背包。

然后就想怎么处理数据才能用上分组背包。

因为是和1的 位置有关,所以先记录每一组的1的位置。然后num数组计数多少个1。

然后,就是,怎么处理记录位置的数组才能得到距离呢。如果直接贪心的话肯定是不对的,如果是01001010010010,贪心的话,就不对了。所以要考虑一下。

怎么处理呢,举例,一开始的位置是0,假设数组a存位置就是a[1]=0,a[2]=2,a[3]=3,a[4]=5,a[5]=9。

然后进行删0个1,删1个1,删2个1,删3个1,删。。。一直删num个1。怎么删呢。然后就模拟所有情况。这样做的意思就是假设只处理这一个串。后面会说为什么这样做。

(写的太乱了,凑活看。。。)

发现有重复的情况,才突然想起来(mdzz),肯定是从两边删才是最完美的呀。就不会有重复了。

但是怎么才能避免呢。贪心肯定不对,然后就想到一种遍历,怎么遍历呢。距离肯定是最后的记录位置的数减去最开始的记录位置的数。我想的就是一个for控制组数,一个for控制删几个数,一个for控制进行操作的两个数的位置,什么意思呢。因为知道有几个数(num数组存的),所以删j个数的话,就是从两边一共删j个数。还是用上面的例子。

a[1]=0,a[2]=2,a[3]=3,a[4]=5,a[5]=9。

这个是什么意思呢。就是删1个1的操作,就是控制位置。我写的是从最后往前推。一直推到头就可以了。然后for循环一边推,一边用数组保存最小值就可以。

但是写的时候智障,只考虑了一直都还有1的情况,没考虑所有1都删掉的情况。还是上面的例子,有5个1,如果5个1都删掉,距离就是0,不是1,这里判断一下。

然后就是写for的时候比较一下这组串中1的个数和要删掉的1的个数哪个小就用哪个作为删j个1的边界值。为什么呢。假设串里就2个1,题目要求删5个1,完全没必要一直删5个1,删2个1就没了,所以比较一下,如果1个个数本来就比要求的删的个数小的话,那肯定是把串里所有的1都删了,所以最后距离是0,这里判断一下就可以。

通过以上的炸裂操作,就可以得到每组串里删j个1的最优值。

自我吐槽:脑子不好,控制位置那里想了好久,最后发现,因为我存位置是从第一个1出现位置开始存的,所以存位置的数组最开始是从1开始的,不是从0开始的。

  1. for(int i=;i<n;i++){ //控制组数
  2. int x=min(k,num[i]); //该组中1的个数和要处理的k个1比较一下,取最小值
  3. for(int j=;j<=x;j++){ //控制删几个1
  4. for(int k=;k<=j;k++){ //控制位置
  5. if(j==num[i]) //1全删完的判断
  6. p[i][j]=;
  7. else
  8. p[i][j]=min(p[i][j],a[i][num[i]-k]-a[i][+j-k]+); //存最短的距离
  9. }
  10. }
  11. }

就是上面这个傻子操作。。。

然后就是怎么用分组背包来得到结果呢。

一篇简短介绍分组背包的博客,传送门:我不想当咸鱼

那么背包的最大能装的质量就是题目要求删的1的个数,就是k。最大质量为k。

然后每组的每个物品的质量就是删几个1,如果是删0个1的,那么质量为0,删1个1的,质量就是2,直接就是p[i][j]的j值。

物品的价值就是距离。因为我写的分组背包是用max求最大值的,所以就要找最大节省的时间(就是存位置的一开始的值减去最短距离就是最大节省时间)

然后就可以进行分组背包的操作了。求出来最大节省的时间,然后总的不逃课的时间-最大节省的时间,就是最少的上课时间。游戏结束。

代码:

  1. //D-数据处理+分组背包(处理炸裂)
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<cstdlib>
  8. using namespace std;
  9. typedef long long ll;
  10. const int maxn=+;
  11. const int inf=+;
  12. #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
  13. int h[maxn][maxn],a[maxn][maxn];
  14. int p[maxn][maxn],num[maxn],dp[maxn];
  15. char s[maxn][maxn];
  16. int main(){
  17. int n,m,k;
  18. ios;
  19. cin>>n>>m>>k;
  20. for(int i=;i<n;i++)
  21. cin>>s[i];
  22. for(int i=;i<n;i++){
  23. for(int j=;j<m;j++)
  24. h[i][j]=s[i][j]-''; //h数组存串
  25. }
  26. memset(num,,sizeof(num));
  27. for(int i=;i<n;i++){ //记录位置
  28. for(int j=;j<m;j++){
  29. if(h[i][j]==){
  30. num[i]++; //记录1的个数
  31. a[i][num[i]]=j; //记录第几个1的位置
  32. }
  33. }
  34. }
  35. for(int i=;i<n;i++){ //初始化
  36. for(int j=;j<=min(k,num[i]);j++)
  37. p[i][j]=inf;
  38. }
  39. for(int i=;i<n;i++){ //i控制组数 处理距离
  40. int x=min(k,num[i]); //找最小的删1的个数
  41. for(int j=;j<=x;j++){ //控制删1的操作
  42. for(int k=;k<=j;k++){ //控制位置
  43. if(j==num[i]) //特判一下
  44. p[i][j]=;
  45. else
  46. p[i][j]=min(p[i][j],a[i][num[i]-k]-a[i][+j-k]+); //还有1存在的正常情况
  47. }
  48. }
  49. }
  50. ll sum=;
  51. for(int i=;i<n;i++)
  52. sum+=p[i][]; //将一开始一个1都不删的距离求和
  53. memset(dp,,sizeof(dp));
  54. for(int i=;i<n;i++) //i控制组数 分组背包
  55. for(int j=k;j>=;j--) //j控制质量
  56. for(int h=;h<=min(k,num[i]);h++) //h控制每组的物品数,h也是物品的质量,想一下就懂了
  57. if(j>=h) //一开始没写,数组可能会越界,写上就对了。。。
  58. dp[j]=max(dp[j-h]+(p[i][]-p[i][h]),dp[j]);
  59. // for(int i=0;i<n;i++)
  60. // {
  61. // for(int j=0;j<=k;j++)
  62. // {
  63. // cout<<p[i][j]<<" ";
  64. // }
  65. // cout<<endl;
  66. // }
  67. // for(int i=0;i<=k;i++)
  68. // {
  69. // cout<<dp[i]<<endl;
  70. // }
  71. // cout<<sum<<endl;
  72. cout<<sum-dp[k]<<endl; //游戏结束
  73. }
  74. //2 7 2
  75. //0100101
  76. //

就这样,这题就是处理数据不好想。。。

就这样吧。溜了。。。

Codeforces 946 D.Timetable-数据处理+动态规划(分组背包) 处理炸裂的更多相关文章

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

    题目链接:http://codeforces.com/problemset/problem/946/D 题目大意:有n个字符串,代表n天的课表,1表示这个时间要上课,0表示不要上课,一天在学校时间为第 ...

  2. Codeforces Round #383 (Div. 2) D 分组背包

    给出一群女孩的重量和颜值 和她们的朋友关系 现在有一个舞台 ab是朋友 bc是朋友 ac就是朋友 给出最大承重 可以邀请这些女孩来玩 对于每一个朋友团体 全邀请or邀请一个or不邀请 问能邀请的女孩的 ...

  3. BZOJ1296 [SCOI2009]粉刷匠 动态规划 分组背包

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1296 题意概括 有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝 ...

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

    题目传送门 神奇的门I 神奇的门II 题目大意 有$n$组学生要上课2次课,有$m$个教室,编号为$1$到$m$.要确定有多少种不同的安排上课的教室的方案(每组学生都是本质不同的),使得它们满足: 每 ...

  5. [HDU 3033] I love sneakers! (动态规划分组背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3033 题意:给你K种品牌,每种品牌有不同种鞋,现在每种品牌至少挑一款鞋,问获得的最大价值,如果不能每种 ...

  6. #分组背包 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 me ...

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

    题目链接:Timetable 题意:Ivan是一个学生,在一个Berland周内要上n天课,每天最多会有m节,他能逃课的最大数量是k.求他在学校的时间最小是多少? 题解:先把每天逃课x节在学校呆的最小 ...

  8. CodeForces - 946D Timetable (分组背包+思维)

    题意 n天的课程,每天有m个时间单位.若时间i和j都有课,那么要在学校待\(j-i+1\)个时间.现在最多能翘k节课,问最少能在学校待多少时间. 分析 将一天的内容视作一个背包的组,可以预处理出该天内 ...

  9. CJOJ 2040 【一本通】分组背包(动态规划)

    CJOJ 2040 [一本通]分组背包(动态规划) Description 一个旅行者有一个最多能用V公斤的背包,现在有n件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2, ...

随机推荐

  1. Python记录1:基础知识常识

    今日内容: 一,Python的数据类型 Python一共有以下几种常见的数据类型:int(整形)  float(浮点型)  str(字符串)  list(列表)   tuple元组  dict(字典) ...

  2. 在TensorFlow中运行程序多次报错:AttributeError: __exit__

    我没有记住语句 with tf.Session() as sess: 多次写成了 with tf.Session as sess: 吃括号这个低级的错误又犯了,真不应该,立下flag:以后再犯相同的错 ...

  3. sitecore系列教程之更改您的个人设置

    在Sitecore控制面板中,您可以设置个人设置,例如密码或区域和语言选项,以使应用程序满足您的需求. 要更改您的个人设置: 在Sitecore Launchpad上,单击“ 控制面板”. 在“控制面 ...

  4. Linux服务器---邮件服务spam

    安装spam spam(SpamAssassin)利用perl来进行文字分析,他会检测邮件的标题.内容.送信人,这样就可以过滤出垃圾邮件 1.安装spam.由于spam的依赖太多,用户一定要使用yum ...

  5. android Observable api请求参数设置注解问题

    android Observable api请求参数设置注解问题 2018-10-29 20:05:24.919 11786-11786/xxx E/wxh: getQuote=USD getBase ...

  6. php CI框架中URL特殊字符处理与SQL注入隐患

    php CI框架中URL特殊字符处理与SQL注入隐患 php CI框架中URL特殊字符有很多是不支持的,导致像c++,括号这些常用的分类,字符都无法正常显示很头痛,而在配置里增加单引号' 反斜杠\ 这 ...

  7. 【JavaScript 6连载】四、apply和call的用法

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  8. python requests接口测试

    Python 标准库中的 urllib2 模块提供了你所需要的大多数 HTTP 功能,但是它的 API 太渣了.它是为另一个时代.另一个互联网所创建的.它需要巨量的工作,甚至包括各种方法覆盖,来完成最 ...

  9. struts2 的入门案例

    下面写一个struts2 的一个小例子 首先需要struts2 的jar    可以在Struts 官网上下载    本人使用的版本是2.5 17 官网地址: http://struts.apache ...

  10. 每日linux命令学习-read命令

    read命令 作用 从标准输入中读取一行. 语法 read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p pro ...