贪心讲题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

3
2 10
1 5
1 7

Sample Output

17
 

类型:时间(花费)为定值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的主要内容,如果未能解决你的问题,请参考以下文章

763. 划分字母区间-贪心算法

7月清北学(zao)堂系列

贪心算法:划分字母区间

8-4讲题

贪心热门问题8:划分字母区间

贪心算法----区间覆盖问题(POJ2376)