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

题目链接:http://codeforces.com/problemset/problem/946/D

题目大意:有n个字符串,代表n天的课表,1表示这个时间要上课,0表示不要上课,一天在学校时间为第一节课到最后一节课的时间。总共,可以逃过k次课,求至少需要在学校多少时间。

解题思路:听了大佬说背包,然后预处理就想了20多分钟,比赛结束,GG。。。先是预处理出v[i][k]即第i天逃k节课的能节约的最多时间,至于怎么求,直接枚举k,然后枚举两端1的位置即可。然后就可以做分组背包了,这就不说了,很简单。

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 const int N=1e3+5;
 8 const int INF=0x3f3f3f3f;
 9
10 char s[N][N];
11 int num[N],pos[N][N],dp[N],v[N][N];         //pos[i][j]对应第i个字符串第j个‘1‘的位置,num[i]记录第i个字符串‘1‘的数量
12                                             //v[i][k]即第i段字符串删除k个1节约的时间
13 int main(){
14     int n,m,lim;
15     scanf("%d%d%d",&n,&m,&lim);
16     for(int i=0;i<n;i++){
17         scanf("%s",s[i]);
18         for(int j=0;j<m;j++){
19             if(s[i][j]==‘1‘){
20                 num[i]++;
21                 pos[i][num[i]]=j;
22             }
23         }
24     }
25     //处理出v[i][k],
26     for(int i=0;i<n;i++){
27         int cnt=0;
28         //枚举k
29         for(int k=0;k<=min(num[i]-1,lim);k++){
30             int res=INF;
31             //左进p个1,右进q个1
32             for(int p=0;p<=k;p++){
33                 int q=(k-p);
34                 res=min(res,pos[i][num[i]-q]-pos[i][p+1]+1);
35             }
36             v[i][k]=m-res;
37         }
38         v[i][num[i]]=m;
39     }
40     //分组背包
41     memset(dp,0,sizeof(dp));
42     for(int i=0;i<n;i++){
43         for(int j=lim;j>=0;j--){
44             for(int k=0;k<=min(j,m);k++){
45                 dp[j]=max(dp[j],dp[j-k]+v[i][k]);
46             }
47         }
48     }
49     printf("%d\n",m*n-dp[lim]);
50     return 0;
51 }

原文地址:https://www.cnblogs.com/fu3638/p/8520285.html

时间: 2024-09-29 09:28:15

Codeforces 946D Timetable(预处理+分组背包)的相关文章

CodeForces 946D Timetable

Timetable 题意:ivan 是一个学生, 他们当地一周有n天, 每天有m节课,每节课一小时, 然后'1'代表的是ivan这个时间段需要上课, 现在ivan可以跳过选择K节课不去上, 他在学校的时间为当天他选择的第一节课到当天的最后一节课,也就是可以跳2端的课, 如果当天的没有课, 当天就不需要去学校.现在求这周ivan去学校的时间最小是多少. 题解:算出不逃课的情况下的总时间, 然后用分组背包(因为每天只能有一种情况, 所以只能在每组里面选一种),跑出逃课k节下最多的逃课时间是多少, 总

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

Codeforces 148E Porcelain [预处理+dp背包]

给出n行数,每行的数目不定(不超过100个),只能从行的两端取数m次,求所取数的和最大值 n (1?≤?n?≤?100) andm (1?≤?m?≤?10000). 看似很难上手 我甚至想每次取一个,然后搜索,,,搜索分支有200个 如果我们知道每行取k个最多能取多少的话 那么 这个问题就变成了 如果我在前i-1行取了j次得到x的破坏值 那么我要再第i行取k次得到get[k]的破坏值 也就是前i行共取了k+j次得到了x+get[k]的破坏值 背包问题 暴力求解出每行取k个最大的破坏值即可(一个滑

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

D. Arpa&#39;s weak amphitheater and Mehrdad&#39;s valuable Hoses 分组背包模板题

http://codeforces.com/problemset/problem/742/D 并查集预处理出所有关系. 一开始的时候,我预处理所有关系后,然后选择全部的时候,另起了一个for,然后再判断. 这样是不对的.因为这样使得同一组里面可能选择了两次. 3 0 2 1 2 3 1 1 3 #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include &

[CF148E] Porcelain (分组背包)

题目链接:http://codeforces.com/problemset/problem/148/E 题目大意:有n组数据,每次可以从任意一组的两端取出1个数,问你取m个数最大能组成多少? 思路:先将这n组数据变成每组内选i个最大能取到多少,就是合成若干个物品,然后就是分组背包问题. 分组背包: 问题有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[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

VijosP1250:分组背包

背景 Wind设计了很多机器人.但是它们都认为自己是最强的,于是,一场比赛开始了~ 描述 机器人们都想知道谁是最勇敢的,于是它们比赛搬运一些物品. 它们到了一个仓库,里面有n个物品,每个物品都有一个价值Pi和重量Wi,但是有些物品放在一起会爆炸,并且爆炸具有传递性.(a和b会爆炸.b和c会爆炸则a和c会爆炸)机器人们可不想因此损失自己好不容易从Wind那里敲诈来的装备,于是它们想知道在能力范围内,它们最多可以拿多少价值的物品. 你能帮助它们吗? 格式 输入格式 每组测试数据第1行为n,Wmax,

HDU-1011 Starship Troopers (树形DP+分组背包)

题目大意:给一棵有根带点权树,并且给出容量.求在不超过容量下的最大权值.前提是选完父节点才能选子节点. 题目分析:树上的分组背包. ps:特判m为0时的情况. 代码如下: # include<iostream> # include<cstdio> # include<vector> # include<cstring> # include<algorithm> using namespace std; const int N=105; const