[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的博客查看
贪心思想:先假设每一项工作都做,将各项工作按截止时间排序后入队,在判断第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 }