Loading

# [USACO09OPEN]Work Scheduling 经典反悔贪心 ##

[USACO09OPEN]Work Scheduling 经典反悔贪心

题意

约翰有太多的工作要做。为了让农场高效运转,他必须靠他的工作赚钱,每项工作花一个单位时间。

他的工作日从 \(0\)时刻开始,有 \(10^9\)个单位时间。在任一时刻,他都可以选择编号 \(1\)\(N\)\(N\)(\(1 \leq N \leq 10^5\)) 项工作中的任意一项工作来完成。 因为他在每个单位时间里只能做一个工作,而每项工作又有一个截止日期,所以他很难有时间完成所有N个工作,虽然还是有可能。 对于第 \(i\)个工作,有一个截止时间 \(D_i\)(\(1\leq D_i \leq 10^9\)),如果他可以完成这个工作,那么他可以获利 \(P_i,(1 \leq P_i \leq 10^9)\)在给定的工作利润和截止时间下,约翰能够获得的利润最大为多少.

分析

限定的选择获得最大价值,我们肯定贪心地选择最大的价值。

对时间排序后,若该物品的价值比当前选的最小的价值还大且以及选满了,那我们就反悔选之前的物品,这样一定是更优的。因此只需要维护一个小根堆。

代码

#include<bits/stdc++.h>
#define pii pair<int,int>
#define eps 1e-7
#define equals(a,b) (fabs(a - b) < eps)
#define fi first
#define se second
using namespace std;
typedef long long ll;

const int maxn = 2e5 + 5;
const ll MOD = 1e9 + 7;

ll rd(){
	ll x = 0;
	int f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9'){
		if(ch == '-')  f = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9'){
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}

int main(){
	int n = rd();
	ll ans = 0;
	priority_queue<int,vector<int>,greater<int>> q;
	vector<pii> v(n);
	for(int i = 0;i < n;i++){
		v[i].fi = rd();
		v[i].se = rd();
	}
	sort(v.begin(),v.end());
	for(int i = 0;i < n;i++){
		if(v[i].fi <= q.size()) {
			if(v[i].se > q.top()) {
				ans -= q.top();
				q.pop();
				q.push(v[i].se);
				ans += v[i].se;
			}
		}
		else {
			q.push(v[i].se);
			ans += v[i].se;
		}
	}
	cout << ans;
}
posted @ 2021-02-28 11:56  MQFLLY  阅读(236)  评论(0编辑  收藏  举报