前言(刮开查看)
这句话是用来占位的,这句话是用来占位的,这句话是用来占位的,这句话是用来占位的,这句话是用来占位的,这句话是用来占位的,这句话是用来占位的,这句话是用来占位的,这句话是用来占位的,这句话是用来占位的,这句话是用来占位的,这句话是用来占位的,这句话是用来占位的……
As everyone knows, XKF ♡ LXY. In order to express my blessing to both of them, I posted this solution, and wish them have a harmonious union lasting a hundred years.
内容敏感故使用洋文,有意愿者自行翻译,我太弱可能编的不对(逃
题目
LXY的演讲 |
难度级别:B; 运行时间限制:1000ms; 运行空间限制:256000KB; 代码长度限制:2000000B |
试题描述
|
有一个演讲大厅需要管理,演讲者LXY等人事先定好了需要演讲的起始时间和中止时间。管理员WXJ想让演讲大厅得到最大可能的使用。他要接受一些预定而拒绝其他的预定,目标是使演讲者使用大厅的时间最长。假设在某一时刻一个演讲结束,另一个演讲就可以立即开始。
|
输入
|
* 第一行为一个整数N,N≤5000,表示申请的数目。
* 接下来n行每行包含两个整数p,k,1 ≤ p < k ≤ 10000,表示这个申请的起始时间和中止时间。 |
输出
|
* 一个数:表示大厅最大可能的使用时间。
|
输入示例
|
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 |
输出示例
|
16
|
我知道大家都想要A了这道题,所以看不懂也没关系,请X*F自取代码。
好了,先不讲八卦,咱们来看看题。
这是一道DP题,不了解的同学可以先放一放。你可以把此题想象成一道时间轴,也就是说,你只需要顺着时间轴走一遍就可以知道答案了。
而存数据的方法与一般的读完就存不同,你只需要存开始的时间点以及其持续的长度就可以了(爆坑:一个时间点可以同时是几个演讲开始的时间点)。而之后可以顺便将最后的一个时间点记下作为循环的边界,然后开始DP。
DP过程主要是每到下一个时间点,先判断是否继承上一个小时,再判断是否有演讲开始,如果有直接在演讲结束的时间点插入一个dp[i],表示到i小时最多的演讲时间,到后来for循环到了是自然会判断是否需要开始演讲。简单的说就是假设每个演讲都批准,又同时假设不批准,因为批准的情况是直接插入的,所以对于中间的时间没有影响,而到了演讲结束的时候再判断。
代码
#include<bits/stdc++.h>
using namespace std;
int dp[5005],t[5005],sum[105][1005],n,maxn;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
sum[t[x]+1][x]=y-x;//每个时间点的开始的每个演讲持续时间。
maxn=max(maxn,y);//寻找最长持续时间。
}
for(int i=0;i<=maxn;i++)
{
int tmp=1;
dp[i]=max(dp[i],dp[i-1]);//判断是原来插入时间好还是继承上一小时好。
while(sum[tmp][i]!=0)//这个时间点开始的所有演讲。
{
dp[i+sum[tmp][i]]=max(dp[i+sum[tmp][i]],dp[i]+sum[tmp][i]);//判断是否需要允许该演讲。
tmp++;
}
}
printf("%d",dp[maxn]);
return 0;
}
@wxfy Jordan~