后悔贪心+P2949 [USACO09OPEN]Work Scheduling G

题意:

给你N个任务,每个任务 i i i 都有截止日期 D i D_{i} Di和报酬 P i P_{i} Pi,每完成一个工作需要耗费1的单位时间,你需要使所得报酬最大并输出。

题目描述

Farmer John has so very many jobs to do! In order to run the farm efficiently, he must make money on the jobs he does, each one of which takes just one time unit.

His work day starts at time 0 and has 1,000,000,000 time units (!). He currently can choose from any of N (1 <= N <= 100,000) jobs

conveniently numbered 1…N for work to do. It is possible but

extremely unlikely that he has time for all N jobs since he can only work on one job during any time unit and the deadlines tend to fall so that he can not perform all the tasks.

Job i has deadline D_i (1 <= D_i <= 1,000,000,000). If he finishes job i by then, he makes a profit of P_i (1 <= P_i <= 1,000,000,000).

What is the maximum total profit that FJ can earn from a given list of jobs and deadlines? The answer might not fit into a 32-bit integer.

输入格式
  • Line 1: A single integer: N

  • Lines 2…N+1: Line i+1 contains two space-separated integers: D_i and P_i

输出格式
  • Line 1: A single number on a line by itself that is the maximum possible profit FJ can earn.

题意翻译

约翰的工作日从 0时刻开始,有 1 0 9 10^{9} 109个单位时间。在任一单位时间,他都可以选择编号1到N 的 N ( 1 < = N < = 1 0 5 ) N(1<=N<=10^{5}) N(1<=N<=105) 项工作中的任意一项工作来完成。工作 i i i的截止时间是 D i ( 1 < = D i < = 1 0 9 ) D_{i}(1<=D_{i}<=10^{9}) Di(1<=Di<=109) ,完成后获利是 。在给定的工作利润和截止时间下,求约翰能够获得的利润最大为多少。

输入

3
2 10
1 5
1 7

输出

17

说明/提示

Complete job 3 (1,7) at time 1 and complete job 1 (2,10) at time 2 to maximize the earnings (7 + 10 -> 17).

分析:

1.先假设如果一个工作有时间去做,就先做了它,将各项工作按截止时间压入一个小根堆。
2.当我们找到一个没法做却价值比当前堆顶高的工作时,我们就放弃那个最小的工作,用做它的时间去做这个价值更高的工作。用优先队列(小根堆)来维护队首元素最小。
3.在判断第 i 项工作做与不做时,若其截至时间符合条件,则将其与队中报酬最小的元素比较,若第 i 项工作报酬较高(后悔),则 ans += a[i].p - q.top()。

复习:

C++优先队列的基本使用方法
在优先队列中,优先级高的元素先出队列。
标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。

  • 优先队列的第一种用法,也是最常用的用法:
 priority_queue < int > q;//通过<操作符可知在整数中元素大的优先级高。故队列由大到小

通过<操作符可知在整数中元素大的优先级高。故队列由大到小

  • 第二种方法:
    如果我们要把元素从小到大输出怎么办呢?
    这时我们可以传入一个比较函数,使用functional.h函数对象作为比较函数。
priority_queue<int,vector<int>,greater<int>>q;

其中
第二个参数为容器类型。
第二个参数为比较函数。

  • 第三种方法:
    自定义优先级(直接在结构体里写,或者写一个函数)
struct node
{
    int x,y;
    bool operator<(const node&a)const{
        return x<a.x;
    }
}s[M];

AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
typedef long long ll;
const int M=1e5+10;

struct node{
    int x,y;
     bool operator<(const node&a)const{
        return x<a.x;
    }
}s[M];
priority_queue<int,vector<int>,greater<int> >q;//"> >"之前要有空格
int n;
ll ans;
int main(){
    cin>>n;
    ans=0;
    for(int i=1;i<=n;i++){
        cin>>s[i].x>>s[i].y;
    }
    sort(s+1,s+n+1);//先对时间排序
    for(int i=1;i<=n;i++){
        if(s[i].x<=q.size()){//当我们找到一个没法做却价值比当前堆顶高的工作时,我们就放弃那个最小的工作,用做它的时间去做这个价值更高的工作。
            if(s[i].y>q.top()){//用优先队列(小根堆)来维护队首元素最小。
                ans=ans+s[i].y-q.top();
                q.pop();
                q.push(s[i].y);
            }
        }
        else{//可以做,就直接放进去
            q.push(s[i].y);
            ans+=s[i].y;
        }
    }
    cout<<ans<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值