WEEK4 周记 作业A题——贪心算法_DDL的恐惧

WEEK4 周记 作业A题——贪心算法_DDL的恐惧

一、题意

1.简述

有 n 个作业,每个作业都有自己的 DDL,如果没有在 DDL 前做完这个作业,那么老师会扣掉这个作业的全部平时分。如何安排做作业的顺序,才能尽可能少扣一点分。

2.输入格式

输入包含T个测试用例。输入的第一行是单个整数T,为测试用例的数量。
每个测试用例以一个正整数N开头(1<=N<=1000),表示作业的数量。
然后两行。第一行包含N个整数,表示DDL,下一行包含N个整数,表示扣的分。

3.输出格式

对于每个测试用例,您应该输出最小的总降低分数,每个测试用例一行。

4.样例

Input

3
3
3 3 3
10 5 1
3
1 3 1
6 2 3
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4

Output

0
3
5

Hint

上方有三组样例。
对于第一组样例,有三个作业它们的DDL均为第三天,ZJM每天做一个正好在DDL前全部做完,所以没有扣分,输出0。
对于第二组样例,有三个作业,它们的DDL分别为第一天,第三天、第一天。ZJM在第一天做了第一个作业,第二天做了第二个作业,共扣了3分,输出3。

二、算法

主要思路

对于第i天,只要ddl大于等于i的任务都能够在这一天完成,所以我们只需要从这些满足条件的任务中选一个分值最大的即可。
还需要注意的是,如果有两个任务 t 1 t_1 t1 t 2 t_2 t2分值相同,且两者都能够在第i天进行,但是 t 1 t_1 t1的ddl要大于 t 2 t_2 t2,那么,这里应该安排 t 2 t_2 t2,因为 t 1 t_1 t1可能能够在后面的空闲的某一天进行,而 t 2 t_2 t2就不能了。
所以我们采取的策略是,按日期从后往前遍历,尽量将遍历经过的每一天都安排上任务,当然要安排能安排的任务中分值最大的(这个时候可以不管ddl,因为是从后往前遍历)。
从最后一个ddl所在的日期开始,我们每到达一天,就将ddl在该天的任务加入一个大根堆(以分值作为唯一比较大小的标准)中,然后取出堆顶元素,这个任务就是安排在这一天执行的任务。
如果遍历完第一天大根堆中还有任务,那堆中任务的分值之和就是我们最终要被扣掉的分数,这个分数是最小的。

该算法的时间复杂度为 O ( n l o g ( n ) ) O(nlog(n)) O(nlog(n))

三、代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
struct pr{
	int a;
	int b;
	bool operator<(const pr& p)const
	{
		return a>p.a;
	}
};
pr pp[1001];
int main()
{
	int T;
	scanf("%d",&T);
	int i,j;
	for(i=0;i<T;i++)
	{
		int n;
		scanf("%d",&n);
		for(j=0;j<n;j++)scanf("%d",&pp[j].a);
		for(j=0;j<n;j++)scanf("%d",&pp[j].b);
		sort(pp,pp+n);//从大到小 
		priority_queue<int> p;
		int ddl=pp[0].a;//只需从最大的ddl所在的日期开始往前遍历 
		j=0;
		for(;ddl;ddl--)
		{//从后往前遍历天数 
			while(pp[j].a==ddl&&j<n)
			{
				p.push(pp[j].b);
				j++;
			}
			if(!p.empty())p.pop();
		}
		int sum=0;
		while(!p.empty())
		{
			sum+=p.top();
			p.pop();
		}
		printf("%d\n",sum);
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值