题目描述:
ZJM 有 n 个作业,每个作业都有自己的 DDL,如果 ZJM 没有在 DDL 前做完这个作业,那么老师会扣掉这个作业的全部平时分。
所以 ZJM 想知道如何安排做作业的顺序,才能尽可能少扣一点分。
请你帮帮他吧!
Input:
输入包含T个测试用例。输入的第一行是单个整数T,为测试用例的数量。
每个测试用例以一个正整数N开头(1<=N<=1000),表示作业的数量。
然后两行。第一行包含N个整数,表示DDL,下一行包含N个整数,表示扣的分。
Output:
对于每个测试用例,您应该输出最小的总降低分数,每个测试用例一行。
思路:
这是一道贪心的题目,扣分最少即得分最多,因此只需要解决如何得分最多就可以了。将n个作业排序,排序规则为按照分数由大到小,然后从第1个作业开始遍历至n,对于第i个作业,从ddl[i]开始往前面扫描,看是否能将其安排下,若能,则所得分数+=v[i],若不能,则抛弃此作业。从第i个作业的ddl前面扫描,可使得当前的作业对其他作业的影响最小,因此此贪心方案是正确的。
遍历了每个作业,并从其ddl开始向前面扫描,所以总的时间复杂度是O(n*max(ddl)),在此题目中,由于ddl最大值和n最大值相同,因此复杂度为O(n^2)
对于数据的加强,O(n^2)显然过于复杂,现在更新算法,使其时间复杂度为O(nlogn)。在上面的算法中,枚举了每一个作业,试图将每个作业安排到某一天,是从作业安排时间的角度出发的。而在下面的算法中,考虑在每一天安排某个作业,即从时间安排作业的角度出发。显然,最后的时间为max(ddl),因此需要预处理出ddl的最大值。然后从这一天开始向前遍历天数。对于第i天,安排的显然是ddl位于这天之后,且得分最多的作业。要想得到得分最多的作业,可使用优先队列进行实时的更新。算法遍历每一天,这个复杂度是n(题目中的n和ddl数量级相同),优先队列处理的时间复杂度为logn级别,因此总的时间复杂度为O(nlogn)
下面是数据简单时的代码: