P2439 [SDOI2005]阶梯教室设备利用


原题链接

P2439
题目类型: 普 及 + / 提 高 {\color{lightgreen} 普及+/提高} +/
AC记录:Accepted

题目大意

读入所有演讲的起始和终止时间,计算最大的可能演讲总时间。

输入格式

第一行包括一个正整数 n n n,为所有的演讲的数目。
以下的 n n n行每行含有两个由空格隔开的整数 p p p k k k。这样的一对整数表示一个演讲由时间 p p p开始到时间 k k k结束。

输出格式

输出唯一的一个整数,为最长的演讲总时间。

S a m p l e \mathbf{Sample} Sample I n p u t \mathbf{Input} Input

12
1 2
3 5
0 4
6 8
7 13
4 6
9 10
9 12
11 14
15 19
14 16
18 20

S a m p l e \mathbf{Sample} Sample O u t p u t \mathbf{Output} Output

16

H i n t & E x p l a i n \mathbf{Hint\&Explain} Hint&Explain
可以选择第 3 3 3个、第 5 5 5个、第 6 6 6个、第 11 11 11个、第 12 12 12个演讲,此时有最长的演讲总时间 16 16 16

数据范围

对于 100 % 100\% 100%的数据, 1 ≤ n ≤ 1 0 4 , 0 ≤ p < k ≤ 3 × 1 0 4 1≤n≤10^4 ,0\le p<k\le 3\times 10^4 1n104,0p<k3×104

解题思路

d p dp dp,就是 d p dp dp
我们可以考虑每次添加一个演讲,依次考虑前面所有可以安排当前演讲的状态,取安排当前演讲所获得的价值的最大值,就可以了。
注意:
1.要取所有数里面的最大值。
如果说有一组数据如下:

-------------------
*****
     *************
       *****3
1 6
6 19
7 13

如果直接输出 f n f_n fn,则答案为 10 10 10。但是实际上答案为 18 18 18,取的是 f 2 f_2 f2的值。


2.在执行前要先按照开始时间从小到大排序
如果又有一组数据如下:

-------------------
*****
            *****
      *****3
1 6
7 12
13 18

如果不排序,答案输出的绝对是 10 10 10。而实际上三个时间段都能被选择,则标准答案为 15 15 15


如果上面的注意事项都做了,那么就大概没什么错误了。状态转移方程如下:
f i f_i fi为前 i i i个请求所能得到的最大使用时间, a i , 1 a_{i,1} ai,1为第 i i i个请求的开始时间, a i , 2 a_{i,2} ai,2为第 i i i个请求的结束时间。则有:
当 1 ≤ j < i 且 a i , 1 ≥ a j , 2 时 , 有 f i = max ⁡ ( f j + a i , 2 − a i , 1 ) 当1\le j<i且a_{i,1}\ge a_{j,2}时,有 f_i=\begin{matrix} \max(f_j+a_{i,2}-a_{i,1}) \end{matrix} 1j<iai,1aj,2,fi=max(fj+ai,2ai,1)
其中 f i f_i fi的初值为 a i , 2 − a i , 1 a_{i,2}-a_{i,1} ai,2ai,1


最后,祝大家早日
请添加图片描述

上代码

#include<algorithm>
#include<iostream>

using namespace std;

struct obj{
	obj(int a=0,int b=0):st(a),ed(b){}
	int st,ed;
};

obj                a[10010];
int                f[10010];
int                n,tar;

bool pd(obj x,obj y)
{
	return x.st<y.st;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
	cin>>n;
	for(int i=1; i<=n; i++)
		cin>>a[i].st>>a[i].ed;
	sort(&a[1],&a[n+1],pd);
	for(int i=1; i<=n; i++)
		f[i]=a[i].ed-a[i].st;
	for(int i=1; i<=n; i++)
		for(int j=1; j<i; j++)
			if(a[i].st>=a[j].ed)
			{
				f[i]=max(f[i],f[j]+a[i].ed-a[i].st);
				tar=max(tar,f[i]);
			}
//	for(int i=1; i<=n; i++)
//		cout<<"f["<<i<<"] = "<<f[i]<<endl;
	cout<<tar<<endl;
	return 0;
} 

完美切题 ∼ \sim

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值