【bzoj1572/Usaco2009 Open】工作安排Job——优先队列

题目链接

分析:因为每个事件的代价(也就是时间)是一样的,因此很容易想到应该是贪心。但是这里我们换一种思路来做:不是从大往小选,而是从前往后选,当时间不够用时就把利润最小的舍弃掉加入当前事件的,所以这里我们要先把事件按照第一维截止时间从小到大,第二维利润从小到大排序,然后枚举1~n,开一个利润从小到大的优先队列。每次枚举到事件i,若此时优先队列的size比当前事件的截止时间小,说明此时队列里的都可以选(因为事件已经按照截止时间排序),直接入队;否则,删除队首(也就是当前利润最小的事件),然后入队。枚举完统计一下还在队列里的事件利润即可。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<algorithm>
 5 const int N=1e5+10;
 6 struct node{
 7     int w;
 8     bool operator <(const node &p)const {return p.w<w;}    
 9 };
10 struct point{
11     int d,p;
12 }e[N];
13 int read(){
14     int ans=0,f=1;char c=getchar();
15     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
16     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
17     return ans*f;
18 }
19 bool cmp(point a,point b){return a.d<b.d||(a.d==b.d&&a.p<b.p);}
20 std::priority_queue<node>q;
21 int main(){
22     long long ans=0;
23     int n=read();
24     for(int i=1;i<=n;i++)
25         e[i].d=read(),e[i].p=read();
26     std::sort(e+1,e+1+n,cmp);
27     for(int i=1;i<=n;i++){
28         if(q.size()<e[i].d)q.push((node){e[i].p});
29         else {
30             q.pop();q.push((node){e[i].p});
31         }
32     }
33     while(!q.empty()){
34         ans+=q.top().w;q.pop();
35     }
36     printf("%lld",ans);
37     return 0;
38 }
Usaco2009

 

posted @ 2017-09-13 14:20  Child-Single  阅读(244)  评论(0编辑  收藏  举报