1164 最高的奖励 V2
- 1.0 秒
- 131,072.0 KB
- 320 分
- 7级题
有N个任务,每个任务有一个最早开始时间,最晚结束时间以及一个对应的奖励。在开始时间之后,结束时间之前完成该任务,就可以获得对应的奖励。完成每一个任务所需的时间都是1个单位时间。有时候完成所有任务是不可能的,因为时间上可能会有冲突,这需要你来取舍。求能够获得的最高奖励。如果某个任务的开始时间 = 结束时间,则表示该任务只能在那一天完成。
收起
输入
第1行:一个数N,表示任务的数量(2 <= N <= 5000) 第2 - N + 1行,每行3个数,中间用空格分隔,表示任务的最早开始时间S[i],最晚结束时间E[i]以及对应的奖励W[i]。(1 <= S[i] <= E[i] <= 10^9,1 <= W[i] <= 10^9)
输出
输出能够获得的最高奖励。
输入样例
7 1 4 20 1 2 60 3 4 70 1 3 40 1 1 30 1 4 50 4 6 10
输出样例
230
分析:
我们首先预处里所有任务的关键点t[i],表示任务最早从这里开始。具体实现:所有任务点区间按左端点排序后,按顺序取从左端点开始第一个还没被取的点。注意这里不考虑右端点。
我们肯定优先选择价值大的,按价值从大到小开始匹配,n个任务最多占n个格子,所以可以对上面处理的t[i]可以离散化一下。对于当前的任务i,他想要的匹配的时间点为tim(在t[i]中的位置即可)。
- 如果tim>n或者t[tim]>a[i].r,肯定这个任务作废。
- 如果tim没有被匹配过,则给他匹配,即pre[tim]=i(pre[j]=i表示j时间的任务为i)。
- 如果tim被匹配过且tim的匹配任务点的右端点<=任务i的右端点,则寻找当前任务i寻找下一个位置tim+1
- 如果tim被匹配过且tim的匹配任务点的右端点>i的右端点,则tim的匹配任务点的右端点是否能匹配下一个位置匹tim+1
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long long ll ;
const int N=1e5+7;
int n;
struct Node
{
LL st,val,en;
friend bool operator <(const Node c,const Node d)
{
return c.val>d.val;
}
}a[N];
int t[N],pre[N];
bool cmp1(Node x,Node y)
{
return x.st<y.st;
}
int findd(int i,int tim)
{
if(tim>n||t[tim]>a[i].en)
return 0;
if(pre[tim]==0)
{
pre[tim]=i;
return 1;
}
if(a[i].en>=a[pre[tim]].en)
{
return findd(i,tim+1);
}
if(findd(pre[tim],tim+1))
{
pre[tim]=i;
return 1;
}
return 0;
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%lld%lld%lld",&a[i].st,&a[i].en,&a[i].val);
}
sort(a+1,a+n+1,cmp1);
for(int i=1;i<=n;i++)
{
if(a[i].st>t[i-1]) t[i]=a[i].st;
else t[i]=t[i-1]+1;
}
sort(a+1,a+n+1);
LL ans=0;
for(int i=1;i<=n;i++)
{
int tim=lower_bound(t+1,t+n+1,a[i].st)-t;
if(findd(i,tim)==1) ans+=a[i].val;
}
printf("%lld\n",ans);
return 0 ;
}