4534-LXY的演讲

前言(刮开查看)

  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~

原文地址:https://www.cnblogs.com/DARTH-VADER-EMPIRE/p/10662930.html