51Nod 最高奖励问题

Question
有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



我想到的第一个思路是:
很麻烦的。。
emm,,
赶时间的话,可忽略。
(按照他能获得的奖励从大到小排序)
(如果相等,就让结束时间靠后的在前面)
(然后用一个数组记录1到1,1到2,1到3,……1到结束时间最大的那个的空间,也就是在这个空间内,和这个数相等或者小于他的有多少)
(用一个bool数组记录在某个时间结束这个时间点是否出现过)
(然后循环枚举,没有出现就设为出现,ans+=奖励)
(操作时同时,这个时间点到最大的时间点之间所有的记录数组都要减一,)
(因为在此空间里又多加了一个数,所以少一个空间)
(然后若是遇到了结束时间相等的,)
(那就判断一下他前面那个结束时间的位置有没有被占)
(他前面那个结束时间不是排完序的那个,,是按照1,2,3,4,5……来的那个)
(如果也被占了的话,就继续往前推)
(在此过程中如果这个结束时间对应的记录空间的数组等于0的话,(那其实一开始就是0了),)
(那就break掉,不用再继续了)。
嗯,,基本就是这样,,
开了很多数组,思路也很麻烦,
可能写错了。。
刚开始mle,,最后wa了一个点,t了三四个点。。

代码是这样的。:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define MAXN 9999
using namespace std;

int n,maxn=-1;
int b[MAXN],x,s;
long long ans;
bool c[MAXN],q;

struct node{
    int end;
    int value;
}a[50002];

bool cmp(node x,node y)
{
    if(x.value !=y.value )
        return x.value >y.value ;
    else return x.end >y.end ;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d",&a[i].end ,&a[i].value );
        maxn=max(maxn,a[i].end );
    }    
    for(int i=1;i<=maxn;++i)
        b[i]=i; 
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;++i)
    {
        x=a[i].end ;
        s=a[i].value ;
        if(b[x])
        {
            if(!c[x])
            {
                ans+=s;
                c[x]=1;
                for(int j=x;j<=maxn;++j)
                    b[j]--;
                continue;
            }
            while(c[x])            
            {
                x--;
                if(x==0)
                    break;
                if(!c[x]&&b[x])
                {
                    c[x]=1;
                    ans+=s;
                    for(int j=x;j<=maxn;++j)
                        b[j]--;
                    break;
                }
            }            
        }
    }
    printf("%lld",ans);
    return 0;
}
75.。


还是要考虑别的简单的思路。。

小根堆啊!!!
按照结束时间从小到大排序!
按次序加,
如果有更优的,就把最小的踢出去!!

具体看代码吧!
手模一遍样例就懂了!
好强的贪心思路。。。

代码:


 1 #include<queue>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 priority_queue<int ,vector<int >,greater<int> >q;
 9 long long n,ans,s;
10 
11 struct node
12 {
13     int end,value;
14 } a[50002];
15 
16 bool cmp(node a,node b)
17 {
18     return a.end<b.end;
19 }
20 
21 int main()
22 {
23     scanf("%d",&n);
24     for(int i=1; i<=n; i++)
25         scanf("%d%d",&a[i].end,&a[i].value);
26     sort(a+1,a+1+n,cmp);
27     for(int i=1; i<=n; i++)
28     {
29         s=a[i].value;
30         if(a[i].end>q.size())
31         {
32             ans+=s;
33             q.push(s);
34         }
35         else
36         {
37             ans+=s;
38             q.push(s);
39             ans-=q.top();
40             q.pop();
41         }
42     }
43     printf("%lld",ans);
44     return 0;
45 }


如果你不开心,那我就把右边这个帅傻子分享给你吧,  

你看,他这么好看,那么深情的望着你,你还伤心吗?  

真的!这照片盯上他五秒钟就想笑了。  

一切都会过去的。

 
原文地址:https://www.cnblogs.com/Mary-Sue/p/9454954.html