贪心讲题1
Posted A_Cherry
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贪心讲题1相关的知识,希望对你有一定的参考价值。
Description
Farmer 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位整型。
Input
第1行:一个整数N. 第2~N+1行:第i+1行有两个用空格分开的整数:D_i和P_i.
Output
输出一行,里面有一个整数,表示最大获利值。
Sample Input
2 10
1 5
1 7
Sample Output
类型:时间(花费)为定值1,报酬不同 ,但因为有时间限制,所以在满足限制的同时让利益最大就是我们的目标了。
so,对于每个工作(按照截止时间排好序之后),我们选一个工作 如果可以做 而且收益最大,那么就尽量去做他。
若目前已经选择的工作数>D_i ,表明已经没有时间去做当前工作了,所以我们就希望从之前选了的工作中,选一个收益最小的扔掉,用当前工作去补上那个位置;
否则的话,那么就直接选他就OK了。
Code:
#include<iostream> #include<cstdio> #include<queue> #include<algorithm> #define N 100010 using namespace std; struct use{int st;long long v;}p[N]; priority_queue<long long>q; bool cmp(use a,use b){return a.st<b.st;} long long ans; int main(){ int n,now(0); scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d%lld",&p[i].st,&p[i].v); sort(p+1,p+n+1,cmp); for (int i=1;i<=n;i++){ ans+=p[i].v;now++;q.push(-p[i].v); if (now>p[i].st){ans+=q.top();q.pop();now--;} } cout<<ans<<endl; }
(解释一下代码)(虽然是别人的,但是的确是很巧妙)
{
首先按照截止时间升序排序之后。
now表示已经选择了多少个工作。
每次一旦有工作来,就把它扔进堆中,表示已经选择了。
(但是实际情况是,不是所以都都可以选的)
所以有一个delete操作
当已经选择的工作数>他的日期。
表明已经没有时间去做当前工作了,所以我们选一个收益最小的扔掉(代码中也有可能是他自己)
(可能会有这个疑问:要是扔掉一个收益最小的之后还是不能做他,这不就不合法了吗?)
(但是answer是合法的。因为 当前的截止时间是>=已经选择的工作中最晚的截止时间的,所以扔掉一个之后,再用当前的去替换一定是合法的。(因为以选择中截止时间最晚的那个是合法的))
}
以上是关于贪心讲题1的主要内容,如果未能解决你的问题,请参考以下文章