【题解】Luogu P2889 [USACO07NOV]挤奶的时间Milking Time

Luogu P2889 [USACO07NOV]挤奶的时间Milking Time

题目描述

传送门
Bessie is such a hard-working cow. In fact, she is so focused on maximizing her productivity that she decides to schedule her next N (1 ≤ N ≤ 1,000,000) hours (conveniently labeled 0..N-1) so that she produces as much milk as possible.

Farmer John has a list of M (1 ≤ M ≤ 1,000) possibly overlapping intervals in which he is available for milking. Each interval i has a starting hour (0 ≤ starting_houri ≤ N), an ending hour (starting_houri < ending_houri ≤ N), and a corresponding efficiency (1 ≤ efficiencyi ≤ 1,000,000) which indicates how many gallons of milk that he can get out of Bessie in that interval. Farmer John starts and stops milking at the beginning of the starting hour and ending hour, respectively. When being milked, Bessie must be milked through an entire interval.

Even Bessie has her limitations, though. After being milked during any interval, she must rest R (1 ≤ R ≤ N) hours before she can start milking again. Given Farmer Johns list of intervals, determine the maximum amount of milk that Bessie can produce in the N hours.

奶牛Bessie在0~N时间段产奶。农夫约翰有M个时间段可以挤奶,时间段f,t内Bessie能挤到的牛奶量e。奶牛产奶后需要休息R小时才能继续下一次产奶,求Bessie最大的挤奶量。

输入输出格式

输入格式:

  • Line 1: Three space-separated integers: N, M, and R
  • Lines 2..M+1: Line i+1 describes FJ’s ith milking interval withthree space-separated integers: starting_houri , ending_houri , and efficiencyi

输出格式:

  • Line 1: The maximum number of gallons of milk that Bessie can product in the N hours

输入输出样例

输入样例#1: 复制

12 4 2
1 2 8
10 12 19
3 6 24
7 10 31

输出样例#1: 复制

43

思路

  • 可以发现从挤奶开始一直到休息完是一个整体,都不能进行转移
  • 所以直接将挤奶时间看作一个整体变成 time+r 进行转移就可以了
  • $f[i]$表示第i分钟的最优收益,$time[i]$ 为这次挤奶的持续时间, $w[i]$ 是这次挤奶的收益
  • 转移方程 $f[i+time[i]+r]=max(f[i+time[i]+r],f[i]+w[i])$

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define re register int
using namespace std;
int read(){
    int x=0,w=1; char ch=getchar();
    while(ch!=‘-‘&&(ch<‘0‘&&ch>‘9‘)) ch=getchar();
    if(ch==‘-‘) w=-1,ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-48,ch=getchar();
    return x*w;
}
int n,m,r,f[2000005],y;
bool tmp[2000005];
struct data{
    int st,tim,w;
}cow[1005];
bool cmp(data cow,data b){
    return cow.st<b.st;
}
int main(){
    //freopen("p2889.in","r",stdin);
    //freopen("p2889.out","w",stdout);
    n=read(),m=read(),r=read();
    n=n+r+10;
    for(re i=1;i<=m;i++){
        cow[i].st=read(),y=read(),cow[i].w=read();
        cow[i].tim=y-cow[i].st+r;
        tmp[cow[i].st]=1;
    }
    sort(cow+1,cow+1+m,cmp);
    int j=1;
    for(re i=0;i<=n;i++){
        f[i]=max(f[i],f[i-1]);
        if(tmp[i]){
            for(;cow[j].st==i;j++){
                f[i+cow[j].tim]=max(f[i+cow[j].tim],f[i]+cow[j].w);
            }
        }
    }
    printf("%d\n",f[n]);
    return 0;
}

?

原文地址:https://www.cnblogs.com/bbqub/p/8423265.html

时间: 2024-08-30 08:03:02

【题解】Luogu P2889 [USACO07NOV]挤奶的时间Milking Time的相关文章

[USACO07NOV]挤奶的时间Milking Time

https://daniu.luogu.org/problemnew/show/2889 按右端点从小到大排序后DP dp[i] 到第i个时间段的最大产奶量 不能按左端点排序,第i段由第j段更新时,第j段可能没挤奶,i,j都处于第k(k<j)段之后的休息时间 #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 1001 int dp[N]; s

题解 luogu P1850 【换教室】

题解 luogu P1850 [换教室] 时间:2019.8.6 一晚上(约 3.5h 写完) 题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有 \(2n\) 节课程安排在 \(n\) 个时间段上.在第 \(i\)(\(1 \leq i \leq n\))个时间段上,两节内容相同的课程同时在不同的地点进行,其中,牛牛预先被安排在教室 \(c_i\) 上课,而另一节课程在教室 \(d_i\) 进行. 在不提交任何申请的情况下,学生们需要

题解 luogu P5021 【赛道修建】

题解 luogu P5021 [赛道修建] 时间:2019.8.9 20:40 时间:2019.8.12 题目描述 C 城将要举办一系列的赛车比赛.在比赛前,需要在城内修建 \(m\) 条赛道. C 城一共有 \(n\) 个路口,这些路口编号为 \(1,2,\dots,n\),有 \(n-1\) 条适合于修建赛道的双向通行的道路,每条道路连接着两个路口.其中,第 \(i\) 条道路连接的两个路口编号为 \(a_i\) 和 \(b_i\),该道路的长度为 \(l_i\).借助这 \(n-1\) 条

题解 Luogu P2499: [SDOI2012]象棋

关于这道题, 我们可以发现移动顺序不会改变答案, 具体来说, 我们有以下引理成立: 对于一个移动过程中的任意一个移动, 若其到达的位置上有一个棋子, 则该方案要么不能将所有棋子移动到最终位置, 要么可以通过改变顺序使这一次移动合法 证明: 考虑到达位置上的那个棋子, 如果它没有到达最终位置, 则我们考虑将该棋子移至下一步, 如果下一步还有没有到达最终位置的棋子, 则也移动它 否则直接调换这两个棋子的移动顺序即可 好的我们去除了题目中的要求: 「移动过程中不能出现多颗棋子同时在某一格的情况」, 接

[LUOGU] P2886 [USACO07NOV]牛继电器Cow Relays

https://www.luogu.org/problemnew/show/P2886 给定无向连通图,求经过k条边,s到t的最短路 Floyd形式的矩阵乘法,同样满足结合律,所以可以进行快速幂. 离散化大可不必sort+unique,因为我们甚至并不在乎相对大小,只是要一个唯一编号,可以开一个桶记录 之所以进行k-1次快速幂,是因为邻接矩阵本身就走了一步了. #include<iostream> #include<cstring> #include<cstdio> u

[题解] luogu P1514 引水入城 DFS + 贪心覆盖区间

原题链 打了一上午,我真是弱爆了 看完题目,可以很显然的想到一种搜法: DFS/BFS第1个到第m个临湖城市,求出干旱区城市能否全有水,很显然,这样时间会炸 此时,我们可以在选择搜第i个临海城市加一个剪枝: if (c[1][i-1] < c[1][i] && c[1][i+1] < c[1][i]) dfs(); 意思说,当且仅当 i 的前一个临湖城市和后一个临海城市的海拔都小于当前临湖城市海拔,我才去搜这个城市 为什么? 你会发现,一个临湖城市要是比自己相邻的临湖城市海拔小

Luogu P2886 [USACO07NOV]牛继电器Cow Relays|最短路,倍增

题目链接 题意:给出一张无向连通图,求S到E经过N条边的最短路. 数据范围:边数\(\le 100\),顶点编号\(\le1000\),\(N\le1 \times 10^6\) 题解: 最短路有三种解法,这种数据范围可使用\(floyd\) 可以用\(f[i][j][k]\)表示从\(i\)到\(j\)经过\(k\)条边的最短路,显然TLE 考虑倍增.预处理\(K=2^k\),此时\(f[i][j][k]=min\{f[i][l][k-1] + f[l][j][k-1]\}\) 将\(n\)二

题解 Luogu P3370

讲讲这题的几种做法: 暴力匹配法 rt,暴力匹配,即把字符串存起来一位一位判相等 时间复杂度$ O(n^2·m) $ 再看看数据范围 $n\le10^5,m\le10^3$ 当场爆炸.当然有暴力分 代码(20pts): #include <bits/stdc++.h> using namespace std; char c[100001][1001]; bool pd(int x, int y) { int l1 = strlen(c[x]), l2 = strlen(c[y]); if(l1

题解 luogu P4415 【[COCI2006-2007#2] KOLONE】

一道纯模拟题. 将两队合并为一个字符串,用一个数组记录蚂蚁的方向,左队为0,右队为1.每一个时间点,两个两个字符地扫一遍字符串.由于0只能往右走,1只能往左走,所以只要在当前的两个字符中,第一个是0,第二个是1,就执行交换(同时交换方向数组和字符串),并且扫描指针加2.否则指针加1. 需要注意的是队伍合并时1左队顺序需要翻转. 自我感觉讲得比较明白了, 下贴代码: #include <bits/stdc++.h> using namespace std; int n1, n2, t, a[10