您的位置:首页 > 运维架构

2016.4 半期 堆+贪心 【UASCO 2009 OPEN GOLD-2】工作安排

2016-04-21 15:08 197 查看
nkoj 1349DescriptionFarmer John 有太多的工作要做啊!!!!!!!!为了让农场高效运转,他必须靠他的工作赚钱,每项工作花一个单位时间。 他的工作日从0时刻开始,有1000000000个单位时间(!)。在任一时刻,他都可以选择编号1~N的N(1 <= N <= 100000)项工作中的任意一项工作来完成。 因为他在每个单位时间里只能做一个工作,而每项工作又有一个截止日期,所以他很难有时间完成所有N个工作,虽然还是有可能。 对于第i个工作,有一个截止时间D_i(1 <= D_i <= 1000000000),如果他可以完成这个工作,那么他可以获利P_i( 1<=P_i<=1000000000 ). 在给定的工作利润和截止时间下,FJ能够获得的利润最大为多少呢?答案可能会超过32位整4000型。 Input第1行:一个整数N. 第2~N+1行:第i+1行有两个用空格分开的整数:D_i和P_i. Output输出一行,里面有一个整数,表示最大获利值。 Sample Input
3
2 10
1 5
1 7
Sample Output
17
分析:
贪心+堆1.将罐头按到期时间有小到大排序2.依次讨论每个罐头:  若当前讨论i号罐头,它的到期时间为date_i,此时,我们最多能选date_i个罐头出来。   所以,我们分两种情况讨论:  <1>若在i之前选的罐头数小于Time_i,我们直接选择i号罐头  <2>若在i之前已选的罐头数>=TIme_i,那么把我们在已选罐头中美味值最小的一个拿来与i号罐头比较,     若i号罐头的美味值大于该罐头,则将该罐头从已选罐头列表中删除,把i号罐头加入到里面。     否则,不选用i号罐头3.我们要从一堆已选的罐头中快速选出美味值最小者,显然用小根堆来维护已选出的罐头即可。
另外,注意数据范围是10^9,要使用long long

一点感受:做这道题的时候首先想到的是动态规划,也想到了堆+贪心,但是却没有细想。所以赛场上不怕有多种思路,不妨列出来,一种一种尝试即可。切不可犹豫不决,对每种方法仔细思考,不能凭主观感受,浅尝辄止。例如本题中,想先到动规是没有错误的,但是仔细研究后会发现,状态有后效性,无法由前面的状态转移的得出。这种时候就应该果断放弃这种思路。

代码如下:
#include<iostream>#include<cstdio>#include<algorithm>#include<queue>#define LL long longusing namespace std;const int maxn=100000+5;int n;struct Work{LL date,w;bool operator < (const Work a)const {return date<a.date;}}s[maxn];priority_queue< LL,vector<LL>,greater<LL> > q; //小根堆int main(){int i;scanf("%d",&n);LL ans=0;for(i=1;i<=n;i++)scanf("%I64d%I64d",&s[i].date,&s[i].w);sort(s+1,s+1+n);for(i=1;i<=n;i++){if(q.size()<s[i].date)q.push(s[i].w);  //没有选出date_i个else if(q.top()<s[i].w){  // 比之前选出的最小的更优q.pop();q.push(s[i].w);}}while(!q.empty())ans+=q.top(),q.pop();printf("%I64d",ans);}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: