有N个任务,每个任务有一个最晚结束时间以及一个对应的奖励。在结束时间之前完成该任务,就可以获得对应的奖励。完成每一个任务所需的时间都是1个单位时间。有时候完成所有任务是不可能的,因为时间上可能会有冲突,这需要你来取舍。求能够获得的最高奖励。
Input
第1行:一个数N,表示任务的数量(2 <= N <= 50000) 第2 - N + 1行,每行2个数,中间用空格分隔,表示任务的最晚结束时间E[i]以及对应的奖励W[i]。(1 <= E[i] <= 10^9,1 <= W[i] <= 10^9)
Output
输出能够获得的最高奖励。
Input 示例
7 4 20 2 60 4 70 3 40 1 30 4 50 6 10
Output 示例
230
首先这是一道水题,没用太多的知识,更多的是思维的活跃
首先确定这一题贪心
贪心 :每次尽量把最大的价值,放到尽量靠后的地方,所以是从后向前找空位
优化1、用二分查找时间
2、选取的工作小于最大的时间跨越
3、记录路径,为了以后查找,少走些弯路,跳跃性查找
主要是1、3优化、2优化,是我做题时凭借1、2强A
我的代码如下
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
using namespace std;
#define MAXN 50008
typedef struct{
int e,v;
}JOB;
JOB w[MAXN];
int A[MAXN],C[MAXN],P[MAXN];//p记录路径
//此题中在时间处理上稍微有些离散化的感觉
int Midfind(int x,int low,int high)
{
while(low<=high){
int mid=(low+high)/2;
if(A[mid]==x)return mid;
else if(A[mid]<x)low=mid+1;
else high=mid-1;
}
return -1;
}
bool comp(JOB x,JOB y){return x.v>y.v;}
int main(){
memset(C,0,sizeof(C));
int i,n,k,j;
cin>>n;
for(i=0;i<n;i++){
cin>>w[i].e>>w[i].v;
A[i]=w[i].e;
}
A[n]=0;
__int64 sum=0,count;count=0;
sort(w,w+n,comp);
sort(A,A+n+1);
for(i=0;i<=n+5;i++)
P[i]=i-1;
for(i=0;i<n;i++){
if(count>=A[n]-A[0]) break;
k=Midfind(w[i].e,0,n);
for(j=k;j>=1;j=P[j])
if(C[j]<A[j]-A[j-1])
{C[j]++;sum+=w[i].v;count++;P[k]=min(j,k-1);break;}
}
printf("%I64d\n",sum);
}