↓ 跳过正文
  1. Posts/

BZOJ 1642: [Usaco2007 Nov]Milking Time 挤奶时间 (dp,类似LIS)

·797 字·2 分钟

#

Time Limit: 5 Sec Memory Limit: 64 MB Submit: 667 Solved: 389 [Submit][Status][Discuss]

Description
#

贝茜是一只非常努力工作的奶牛,她总是专注于提高自己的产量。为了产更多的奶,她预计好了接下来的N (1 ≤ N ≤ 1,000,000)个小时,标记为0..N-1。 Farmer John 计划好了 M (1 ≤ M ≤ 1,000) 个可以挤奶的时间段。每个时间段有一个开始时间(0 ≤ 开始时间 ≤ N), 和一个结束时间 (开始时间 < 结束时间 ≤ N), 和一个产量 (1 ≤ 产量 ≤ 1,000,000) 表示可以从贝茜挤奶的数量。Farmer John 从分别从开始时间挤奶,到结束时间为止。每次挤奶必须使用整个时间段。 但即使是贝茜也有她的产量限制。每次挤奶以后,她必须休息 R (1 ≤ R ≤ N) 个小时才能下次挤奶。给定Farmer John 计划的时间段,请你算出在 N 个小时内,最大的挤奶的量。

Input
#

第1行三个整数N,M,R.接下来M行,每行三个整数Si,Ei,Pi.

Output
#

最大产奶量.

Sample Input
#

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

Sample Output
#

43

HINT
#

注意:结束时间不挤奶

思路:这题很像LIS啊。。由于每次结束要休息R的时间,所以把结束时间+R就好。

然后按照开始时间排序。

dp[i]表示前i个任务安排最大的挤奶量。

初始化dp[i] = a[i].val

转移的时候 dp[i] = max(dp[i],dp[j]+a[i].val) (j<i&&a[j].r<=a[i].l)

代码实现
 1/* ***********************************************
 2Author :111qqz
 3Created Time :2016年04月10日 星期日 01时50分11秒
 4File Name :code/bzoj/1642.cpp
 5************************************************ */
 6
 7#include <cstdio>
 8#include <cstring>
 9#include <iostream>
10#include <algorithm>
11#include <vector>
12#include <queue>
13#include <set>
14#include <map>
15#include <string>
16#include <cmath>
17#include <cstdlib>
18#include <ctime>
19#define fst first
20#define sec second
21#define lson l,m,rt<<1
22#define rson m+1,r,rt<<1|1
23#define ms(a,x) memset(a,x,sizeof(a))
24typedef long long LL;
25#define pi pair < int ,int >
26#define MP make_pair
27
28using namespace std;
29const double eps = 1E-8;
30const int dx4[4]={1,0,0,-1};
31const int dy4[4]={0,-1,1,0};
32const int inf = 0x3f3f3f3f;
33const int N=1E3+7;
34struct node
35{
36    int l,r;
37    int val;
38
39    bool operator < (node b)const
40    {
41	if (l==b.l) return r<b.r;
42	return l<b.l;
43    }
44}a[N];
45int n,m,R;
46int sum;
47int dp[N];
48
49int main()
50{
51	#ifndef  ONLINE_JUDGE
52	freopen("code/in.txt","r",stdin);
53  #endif
54
55	scanf("%d %d %d",&n,&m,&R);   //有点LIS的感觉...
56	for ( int i = 1 ; i <= m ; i++)
57	{
58	    scanf("%d %d %d",&a[i].l,&a[i].r,&a[i].val);
59	    a[i].r += R;
60	    a[i].r = min(a[i].r,n);
61	}
62	sort(a+1,a+m+1);
63
64	ms(dp,0);
65	for ( int i = 1 ;i  <= m ; i++) dp[i] =  a[i].val;
66
67//	for ( int i = 1 ; i <= m ; i++) cout<<dp[i]<<" ";
68//	cout<<endl;
69	int ans = -1;
70	for ( int i = 2 ; i <= m ; i++)
71	{
72	    for ( int j = 1 ; j < i ; j++)
73	    {
74		if (a[j].r<=a[i].l)
75		{
76		    dp[i] = max(dp[i],dp[j]+a[i].val);
77		}
78	    }
79//	    for ( int j = 1 ; j <= m ; j++) cout<<dp[j]<<" ";
80//	    cout<<endl;
81	    ans = max(ans,dp[i]);
82	}
83
84	printf("%d\n",ans);
85
86
87  #ifndef ONLINE_JUDGE
88  fclose(stdin);
89  #endif
90    return 0;
91}

相关文章

hdu 1950 Bridging signals (LIS)

·445 字·1 分钟
题目链接 题意:有两跟柱子并排竖直放置,每根柱子有n个结点,从上往下标号1..n, 两根柱子间的结点间要连线,给出计划连接的情况。a[i]表示左边结点i连接右边结点a[i].但是要求连线不能交叉,所以计划可能不能全部执行。现在问最多能连接多少条线。 思路:由于不能交叉,而左边的结点是按照顺序给出的,所以右边连接的结点只能是越来越大。其实就是求a[i]的最长上升子序列。感觉算是LIS的一个比较巧妙的应用? 由于n还是很大。所以必须nlogn的做法。

BZOJ 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐(LIS nlogn解法)

·1202 字·3 分钟
1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 # Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1282 Solved: 766 [Submit][Status][Discuss] Description # 为了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐。每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想所有第3批就餐的奶牛排在队尾,队伍的前端由设定为第1批就餐的奶牛占据,中间的位置就归第2批就餐的奶牛了。由于奶牛们不理解FJ的安排,晚饭前的排队成了一个大麻烦。 第i头奶牛有一张标明她用餐批次D_i(1 <= D_i <= 3)的卡片。虽然所有N(1 <= N <= 30,000)头奶牛排成了很整齐的队伍但谁都看得出来,卡片上的号码是完全杂乱无章的。 在若干次混乱的重新排队后,FJ找到了一种简单些的方法:奶牛们不动,他沿着队伍从头到尾走一遍把那些他认为排错队的奶牛卡片上的编号改掉,最终得到一个他想要的每个组中的奶牛都站在一起的队列,例如111222333或者333222111。哦,你也发现了,FJ不反对一条前后颠倒的队列,那样他可以让所有奶牛向后转,然后按正常顺序进入餐厅。 你也晓得,FJ是个很懒的人。他想知道,如果他想达到目的,那么他最少得改多少头奶牛卡片上的编号。所有奶牛在FJ改卡片编号的时候,都不会挪位置。

最长上升子序列nlogn解法

·856 字·2 分钟
首先回顾一下n^2的做法。 状态转移方程为dp[i] =max(1,dp[j]) (1=<j<=i-1&&a[i]>a[j]) 1for ( int i = 1 ; i <= n ; i++) cin>>a[i]; 2 3 for ( int i = 1 ; i <= n ; i++) 4 { 5 dp[i] = 1; 6 for ( int j = 1 ; j < i ; j++) 7 { 8 if (a[i]>a[j]) 9 dp[i] = max(dp[i],dp[j]+1); 10 } 11 ans = max(ans,dp[i]); 12 } 然后我们发现,使得dp[i]得到同一个值的dp[j]可能有多个,那么选择哪个呢? 假设 x<y<i,a[x]<a[y],dp[x]==dp[y],那么我们选择x好还是y好呢? 显然是x好。为什么?因为选择x潜力大。因为可能在x,y之间存在一个z,满足a[x]<a[z]<a[y],如果选择a[y],就没有办法选择可能使长度更长的a[z]了。通俗得说。。我们要求的是最长上升子序列。。你一开始就弄那么大。。。后面还上哪上升去啊。。。长度小啊。。。

BZOJ 1641: [Usaco2007 Nov]Cow Hurdles 奶牛跨栏 (floyd)

·845 字·2 分钟
1641: [Usaco2007 Nov]Cow Hurdles 奶牛跨栏 # Time Limit: 5 Sec Memory Limit: 64 MB Submit: 531 Solved: 344 [Submit][Status][Discuss] Description # Farmer John 想让她的奶牛准备郡级跳跃比赛,贝茜和她的伙伴们正在练习跨栏。她们很累,所以她们想消耗最少的能量来跨栏。 显然,对于一头奶牛跳过几个矮栏是很容易的,但是高栏却很难。于是,奶牛们总是关心路径上最高的栏的高度。 奶牛的训练场中有 N (1 ≤ N ≤ 300) 个站台,分别标记为1..N。所有站台之间有M (1 ≤ M ≤ 25,000)条单向路径,第i条路经是从站台Si开始,到站台Ei,其中最高的栏的高度为Hi (1 ≤ Hi ≤ 1,000,000)。无论如何跑,奶牛们都要跨栏。 奶牛们有 T (1 ≤ T ≤ 40,000) 个训练任务要完成。第 i 个任务包含两个数字 Ai 和 Bi (1 ≤ Ai ≤ N; 1 ≤ Bi ≤ N),表示奶牛必须从站台Ai跑到站台Bi,可以路过别的站台。奶牛们想找一条路径从站台Ai到站台Bi,使路径上最高的栏的高度最小。 你的任务就是写一个程序,计算出路径上最高的栏的高度的最小值。

BZOJ 1640/1692 : [Usaco2007 Nov]Best Cow Line 队列变换 (贪心)

·1568 字·4 分钟
1640: [Usaco2007 Nov]Best Cow Line 队列变换 # Time Limit: 5 Sec Memory Limit: 64 MB Submit: 710 Solved: 373 [Submit][Status][Discuss] Description # FJ打算带着他可爱的N (1 ≤ N ≤ 2,000)头奶牛去参加“年度最佳老农”的比赛。在比赛中,每个农夫把他的奶牛排成一列,然后准备经过评委检验。比赛中简单地将奶牛的名字缩写为其头字母(the initial letter of every cow),举个例子,FJ带了Bessie, Sylvia,和Dora,那么就可以缩写为BSD. FJ只需将奶牛的一个序列重新排列,然后参加比赛。他可以让序列中的第一头奶牛,或者最后一头走出来,站到新队列的队尾。利欲熏心的FJ为了取得冠军,他就必须使新队列的字典序尽量小。给你初始奶牛序列(用头字母)表示,然后按照上述的规则组成新序列,并使新序列的字典序尽量小。