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 pic[MAXN][MAXN];
vector<int> v[MAXN];
int t[MAXN][MAXN];
int dp[MAXN][MAXN];
int main(){
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 1; i <= n; ++i){
        scanf("%s", pic[i]);
    }
    for(int i = 1; i <= n; ++i){
        for(int j = 0; j < m; ++j){
            if(pic[i][j] == ‘1‘){
                v[i].push_back(j);
            }
        }
    }
    for(int i = 1; i <= n; ++i){
        int len = v[i].size();
        int mi = min(len, k);
        for(int j = 0; j <= mi; ++j){//逃课数
            int rest = len - j;
            if(rest == 0){//今天不用上课
                t[i][j] = 0;
                continue;
            }
            int Mi = INF;
            for(int w = 0; w < len; ++w){
                int et = w + rest - 1;
                if(et >= len) break;
                Mi = min(Mi, v[i][et] - v[i][w] + 1);
            }
            t[i][j] = Mi;
        }
    }
    for(int i = 1; i <= n; ++i){
        for(int j = 0; j <= k; ++j){
            dp[i][j] = INF;
            for(int w = 0; w <= j; ++w){
                dp[i][j] = min(dp[i][j], dp[i - 1][w] + t[i][j - w]);
            }
        }
    }
    printf("%d\n", dp[n][k]);
    return 0;
}

  

原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/8542262.html

时间: 2024-09-29 15:49:41

Timetable CodeForces - 946D (预处理+背包)的相关文章

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 946D Timetable(预处理+分组背包)

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

CodeForces 946D Timetable

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

CodeForces - 864E (背包+路径)

链接:http://codeforces.com/contest/864/problem/E 给出n个物品,以及每个物品的拿取所需时间,和最终时间(最终时间-1为可以拿取的时间),以及物品的价值. 问你可以拿到的最大价值值和一共拿取几件.同一时间只能够拿取一件,按照最大价值的拿取顺序输出. 思想:利用背包的特性,因为有最终时间和所需时间,利用01背包然后找去最佳拿取时间,最后利用vector将上一时间的物品,转化到此时. #include<cstdio> #include<cstring

codeforces 543A 完全背包

安排n个人写m行代码,每个人每行会出a[i]个bug,求最多出现b个bug的方案数. 一个二维的完全背包,每个人有两个状态:写j行代码出k个bug dp[i][j][k] 前i个程序员写钱j行出现k个bug的方案数. dp[i][j][k] = dp[i][j-1][k-a[i]] + dp[i-1][j][k]; 注意这里数组会超内存,需要用滚动数组. #include <iostream> using namespace std; int n, m, b; long long mod; l

Codeforces 336C 0-1背包

题意:每个水果有两个值,一个美味度 a,一个卡路里 b,从中挑选一些,要求 sum(aj) / sum(bj) = k,使得 sum(a) 最大. 分析:没有那个条件就是一个01背包,可以转换,对公式变形,每个水果的重量为 a[i] - b[i] *k ,那么无论怎么挑选,都满足那个条件,价值是 a[i] 但是,a[i] - b[i] *k 可能为负,那么可以分类讨论,背包容量10000即可,最后枚举背包容量,能够达到的值是两个部分的和. #include <bits/stdc++.h> us

H - Fire CodeForces - 864E 01背包

https://codeforces.com/problemset/problem/864/E 这个题目要把这个按照物品毁灭时间进行排序,如果时间短就要排在前面,这个是因为要保证之后的物品的拯救不会影响到之前的. #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <stack> #include <vector> #inc

【 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> #

[训练日志] 7月22-31日

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "PingFang SC"; color: #454545 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Times New Roman"; color: #454545; min-height: 15.0px } span.s1 { } span.s2 { font: 12.0px "