演讲大厅安排 —— 题解

演讲大厅安排

Description

有一个演讲大厅需要我们管理,演讲者们事先定好了需要演讲的起始时间和中止时间。我们想让演讲大厅得到最大可能的使用。我们要接受一些预定而拒绝其他的预定,目标是使演讲者使用大厅的时间最长。假设在某一时刻一个演讲结束,另一个演讲就可以立即开始。

请依据演讲者的申请,计算出演讲大厅最大可能的使用时间

Input

第一行为一个整数 N,N≤5000,表示申请的数目。

以下 n 行每行包含两个整数 p,k,1 ≤ p < k ≤ 30000,表示这个申请的起始时间和终止时间。

Output

包含一个整数,表示大厅最大可能的使用时间。

Sample Input 1 

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

Sample Output 1

16

这是一道基于时间轴的DP,也就是说,你只需要顺着时间轴走一遍就可以知道答案了;

首先存数据的方法与一般的直接存不同,只用存开始的时间点以及其持续的长度就可以了(值得注意的是一个时间点可以同时是几个演讲开始的时间点);

存数据是可以顺便将最后的一个时间点记下作为for循环的边界,然后开始DP;

每到下一个时间点,先判断是否继承上一个小时,再判断是否有演讲开始,如果有直接在演讲结束的时间点插入一个dp[i],表示到i小时最多的演讲时间,到后来for循环到了是自然会判断是否需要开始演讲(好像有点抽象),简单的说就是假设每个演讲都批准,又同时假设不批准,因为批准的情况是直接插入的,所以对于中间的时间没有影响,而到了演讲结束的时候再判断;

这样讲起来可能太抽象,还是上代码:

#include<bits/stdc++.h>
using namespace std;
int n,sj,dp[30001],t[30001],ma[100][30001];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int x,y;
		cin>>x>>y;
		ma[++t[x]][x]=y-x;//每个时间点的每个开始的演讲的持续时间
		sj=max(sj,y);//最长的持续时间
	}
	for(int i=0;i<=sj;i++)
	{
		dp[i]=max(dp[i],dp[i-1]);//判断是原来插入的时间好还是继承上一小时的好
		int tmp=1;
		while(ma[tmp][i]!=0)//枚举这个点开始的每个演讲
		{
			dp[i+ma[tmp][i]]=max(dp[i+ma[tmp][i]],dp[i]+ma[tmp][i]);//判断是否插入
			tmp++;
		}
		//cout<<i<<" "<<dp[i]<<endl;
	}
	cout<<dp[sj];
}

如果还有点懵逼可以做一做“饥饿的奶牛”;

猜你喜欢

转载自blog.csdn.net/GENE1997/article/details/82954586
今日推荐