原题链接
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 1≤n≤104,0≤p<k≤3×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}
当1≤j<i且ai,1≥aj,2时,有fi=max(fj+ai,2−ai,1)
其中
f
i
f_i
fi的初值为
a
i
,
2
−
a
i
,
1
a_{i,2}-a_{i,1}
ai,2−ai,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 ∼