[USACO]工作调度

约翰有太多的工作要做。为了让农场高效运转,他必须靠他的工作赚钱,每项工作花一个单位时间。 他的工作日从0时刻开始,有10^9个单位时间。在任一时刻,他都可以选择编号1~N的N(1 <= N <= 10^6)项工作中的任意一项工作来完成。 因为他在每个单位时间里只能做一个工作,而每项工作又有一个截止日期,所以他很难有时间完成所有N个工作,虽然还是有可能。 对于第i个工作,有一个截止时间D_i(1 <= D_i <= 10^9),如果他可以完成这个工作,那么他可以获利P_i( 1<=P_i<=10^9 ). 在给定的工作利润和截止时间下,约翰能够获得的利润最大为多少.

 

作者: witliu 更新时间: 2017-07-22 10:10  在Ta的博客查看  5 


贪心思想:先假设每一项工作都做,将各项工作按截止时间排序后入队,在判断第i项工作做与不做时,若其截至时间符合条件,则将其与队中报酬最小的元素比较,若第i项工作报酬较高,则ans+=a[i].p-q.top()。用优先队列(小根堆)来维护队首元素最小。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 typedef long long ll;
 7 const int maxn=1e6+7;
 8 ll n,ans;
 9 struct Node{
10   ll d,p;
11 }node[maxn];
12 priority_queue<ll,vector<ll>,greater<ll> >q;
13 bool cmp(Node a,Node b){
14   return a.d<b.d;
15 }
16 int main(){
17   cin>>n;
18   for(ll i=1;i<=n;i++) cin>>node[i].d>>node[i].p;
19   sort(node+1,node+n+1,cmp);
20   for(ll i=1;i<=n;i++){
21     if(node[i].d>q.size()){
22       ans+=node[i].p;q.push(node[i].p);
23     }
24     else{
25       if(node[i].p>q.top()){
26         ans+=node[i].p-q.top();q.pop();q.push(node[i].p); 
27       }
28     }
29   }
30   cout<<ans<<endl;
31   return 0;
32 } 

 

posted @ 2018-09-23 11:35  lcan  阅读(301)  评论(0编辑  收藏  举报