截止日期

问题描述

某学科老师布置了n个题目,每个题目都有相应的分数及截止日期。各个题目的分数及截止日期可能并不相同。对某题目而言,如果在该题目的截止日期前完成则可获得对应的分数,否则无法得分。假设每个题目均需要花费一天的时间来完成,这期间无法完成其他题目。请你设计算法指定题目的完成计划,从而使总的得分最大。

下面给出一个包含了7个题目及相应的分数、截止日期的实例:

 对该实例而言,得分最大的作业完成方案为花费4天时间依次完成题目2,6,3,7。得分为15。

输入格式

输入数据第一行为一个整数n (0≤n ≤10000), 表示题目数目
之后n行各有两个整数, 第i行为 pi, di (1≤pi, di≤10000),分别表示第i个题目的分数和截止时间

输出格式

一个整数, 为当前条件下的最大得分

样例输入

50 2 

10 1 

20 2 

30 1

样例输出

80

题解

假设有k道题目在第i天截止,为了得分最大,显然优先选得分高的题

考虑按截止日期从小到大,分数从高到低排序,这样可以保证同一截止日期先做分数高的题

这样可以过样例,但是对于如下数据:

7

1 2

1 2

5 5

5 5

5 5

5 5

5 5

显然最优解是5天做5道5分的题,但是上述算法会用前两天做截止日期为2的那两题,因为上述算法优先考虑截止日期,可能会有足够多的高分题截止日期很晚,但是做完这些题会导致一些截止日期早的低分题做不了,而上述算法会优先做截止日期早的题,即可能把最优解中不用做的题做了,导致了错误答案

由此可知正确算法应该优先考虑高分再考虑截止日期

考虑对题目按分数从高到低排序

显然一道题能做的最晚时间是它的截止日期

但是轮到这道题时它的截止日期可能已经被其它题占了,这时只能一天天往前推到最晚的没被占用的一天

一道题不在最优解中的条件是从它的截止日期开始一直往前推到第0天都被占用了

判断一道题不在最优解中的时间复杂度是它的截止日期的大小

截止日期最大为10000,题目总数最多为10000,假设有10000道题每道题截止时间都是10000,每道题都往前推所需时间为0+1+2+……+9999≈100002,

也就是说最坏情况下可能会超时

考虑并查集压缩路径,f[i]表示截止日期为i的最晚的没被占用的天(即不超过i的最晚的未被占用的日期),初始时f[i]=i,当f[i]被占用时将f[i]更新为find(f[i]-1) (find为路径压缩函数),这样可以用接近O(1)的时间找到截止时间为i的没被占用的最晚的时间,当f[i]为0时就表示从第0天到第i天都被占用了

 

 

 1 #include <algorithm>
 2 #include <cstdio>
 3 int n,t,ans;
 4 int f[10005];
 5 struct node{
 6     int p,d;
 7 }a[10005];
 8 bool cmp(node x,node y)
 9 {
10     return x.p>y.p;
11 }
12 int find(int x)
13 {
14     if (f[x]==x) return x;
15     return f[x]=find(f[x]);
16 }
17 int main()
18 {
19     int i,j,x;
20     scanf("%d",&n);
21     for (i=1;i<=n;i++)
22       scanf("%d%d",&a[i].p,&a[i].d);
23     std::sort(a+1,a+n+1,cmp);
24     for (i=1;i<=10000;i++)
25       f[i]=i;
26     t=1;
27     for (i=1;i<=n;i++)
28     {
29         x=find(a[i].d);
30         if (x) 
31           ans+=a[i].p,
32           f[x]=find(f[x]-1);
33     }
34     printf("%d",ans);
35     return 0;
36 }

 

posted @ 2023-05-27 23:55  SAKURA12  阅读(238)  评论(0编辑  收藏  举报