51nod-1163 最高的奖励

1163 最高的奖励 

基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题

 收藏

 关注

有N个任务,每个任务有一个最晚结束时间以及一个对应的奖励。在结束时间之前完成该任务,就可以获得对应的奖励。完成每一个任务所需的时间都是1个单位时间。有时候完成所有任务是不可能的,因为时间上可能会有冲突,这需要你来取舍。求能够获得的最高奖励。

Input

第1行:一个数N,表示任务的数量(2 <= N <= 50000)
第2 - N + 1行,每行2个数,中间用空格分隔,表示任务的最晚结束时间E[i]以及对应的奖励W[i]。(1 <= E[i] <= 10^9,1 <= W[i] <= 10^9)

Output

输出能够获得的最高奖励。

Input示例

7
4 20
2 60
4 70
3 40
1 30
4 50
6 10

Output示例

230

思路:优先队列/贪心+并查集

一:优先队列-由后向前:先将任务按照完成时间由大到小排序,由最晚完成时间开始安排任务,将所有可以安排的任务放入优先队列Q(价值大的优先),每次安排队列Q.top()即可,由于E[i]<=10^9,可能会超时,因此当队列Q中为空时,可将时间直接跳到下一任务上。

二:优先队列-由前向后:将任务按照完成时间由小到大排序,由最早完成时间开始安排任务,将任务放入优先队列Q(价值小的优先)中,若当前任务的完成时间大于队列中的任务个数,则将最小价值的出队即可。

三:贪心+并查集:将任务按照价值由大到小排序,先安排价值大的任务,按照贪心策略,应该将其安排在它最晚时间点上,对于已经安排的时间点,用并查集记录其前面最近的未安排的时间点,由于E[i]<=10^9太大,而n<=50000,因此对于E[i]>n的任务说明它安排在任意时间点上,因此可以将其修改为n。这样每次查询e[i]点所能够安排的最大时间点,若其为0说明没有时间点可以安排,否则修改其记录值。

Code 1:

//优先队列-由后到前 
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;

struct node{
	int time;
	int w;
	bool operator<(const node &p)const{
		return time>p.time;
	}
};
const int MAX_N=100005;
int n;
node a[MAX_N];

int main()
{
	ios::sync_with_stdio(false);
	while(cin>>n){
		LL ans=0;
		priority_queue<LL> Q; 
		for(int i=0;i<n;++i)
			cin>>a[i].time>>a[i].w;
		sort(a,a+n);
		int t=a[0].time,k=0;
		while(t){
			while(a[k].time>=t&&k<n){
				Q.push(a[k++].w);
			}
			if(!Q.empty()){
				ans+=Q.top();	Q.pop();
			}else	t=a[k].time+1; //队列为空则可以直接到下一任务点 
			t--;
		}
		cout<<ans<<endl;
	}
	
	return 0;
}

Code 2:

//优先队列-由前到后 
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;

struct node{
	int time;
	int w;
	bool operator<(const node &p)const{
		return time<p.time;
	}
};
const int MAX_N=100005;
int n;
node a[MAX_N];

int main()
{
	ios::sync_with_stdio(false);
	while(cin>>n){
		LL ans=0;
		priority_queue<int,vector<int>,greater<int>> Q; 
		for(int i=0;i<n;++i)
			cin>>a[i].time>>a[i].w;
		sort(a,a+n);
		for(int i=0;i<n;++i)
		{
			ans+=a[i].w;	Q.push(a[i].w);
			if(a[i].time<Q.size()){
				ans-=Q.top();	Q.pop();
			}
		}
		cout<<ans<<endl;
	}
	
	return 0;
}

Code 3:

//贪心-并查集
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;

struct node{
	int time;
	int w;
	bool operator<(const node &p)const{
		return w>p.w;
	}
};
const int MAX_N=50005;
int n;
int id[MAX_N];
node a[MAX_N];

int Find(int x);
int main()
{
	ios::sync_with_stdio(false);
	while(cin>>n){
		for(int i=0;i<n;++i)
		{
			cin>>a[i].time>>a[i].w;
			id[i]=i;
			if(a[i].time>n)	a[i].time=n;
		}
		id[n]=n;
		sort(a,a+n);
		for(int i=0;i<n;++i)
			if(Find(id[a[i].time]))	id[Find(id[a[i].time])]-=1;
			else	a[i].w=0;
		LL ans=0;
		for(int i=0;i<n;++i)
			ans+=a[i].w;
		cout<<ans<<endl;
	} 
	
	return 0;
}

int Find(int x)
{
	if(id[x]!=x)	id[x]=Find(id[x]);
	return id[x];
}

猜你喜欢

转载自blog.csdn.net/C_13579/article/details/81203539