Week4 作业 A - DDL 的恐惧

题目

ZJM 有 n 个作业,每个作业都有自己的 DDL,如果 ZJM 没有在 DDL 前做完这个作业,那么老师会扣掉这个作业的全部平时分。

所以 ZJM 想知道如何安排做作业的顺序,才能尽可能少扣一点分。

请你帮帮他吧!

Input

输入包含T个测试用例。输入的第一行是单个整数T,为测试用例的数量。

每个测试用例以一个正整数N开头(1<=N<=1000),表示作业的数量。

然后两行。第一行包含N个整数,表示DDL,下一行包含N个整数,表示扣的分。

Output

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

Sample 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

Sample Output

0
3
5

Hint

上方有三组样例。

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

对于第二组样例,有三个作业,它们的DDL分别为第一天,第三天、第一天。ZJM在第一天做了第一个作业,第二天做了第二个作业,共扣了3分,输出3。

解题思路

这道题用贪心算法解。首先我们把题目给出的任务数据多关键字排序,第一是截止时间降序,第二是分值降序。
然后我们从最后一天开始往前安排,每天首先把符合条件的任务,即DDL大于等于当前天数的所有任务加入到优先级队列中,然后每天从优先级队列中取出时间DDL最靠近的分值最大的一天。最后,统计剩余任务的分值并输出。

程序代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<list>
#include<queue>
#include<algorithm>
#include <functional>


using namespace std;
struct node { //DDL节点
	int t;
	int v;
	node(int tt, int vv) :t(tt), v(vv) {

	}
	bool operator<(const node& n)const {
		if (v != n.v)return v < n.v;
		return t < n.t;
	}
	bool operator>(const node& n)const {
		if (v != n.v)return v > n.v;
		return t > n.t;
	}
};




int main() {
	int t;
	cin >> t;
	for (int t1 = 0; t1 < t; t1++) { //获取输入的DDL
		int n;
		cin >> n;

		int* t = new int[n]; //截止时间
		int* v = new int[n]; //扣的分
		for (int i = 0; i < n; i++) {
			scanf("%d", &t[i]);
		}
		for (int i = 0; i < n; i++) {
			scanf("%d", &v[i]);
		}
		for (int i = 0; i < n; i++) { //排序,第一按DDL降序,第二按扣分降序排
			for (int j = i; j < n; j++) {
				if (t[i] < t[j]) {
					int tmp1 = t[i];
					int tmp2 = v[i];
					t[i] = t[j];
					v[i] = v[j];
					t[j] = tmp1;
					v[j] = tmp2;
				}///
				else if (t[i] == t[j]) {
					if (v[i] < v[j]) {
						int tmp1 = t[i];
						int tmp2 = v[i];
						t[i] = t[j];
						v[i] = v[j];
						t[j] = tmp1;
						v[j] = tmp2;
					}
				}
			}
		}
		int current = 0;
		priority_queue<node> p1; //优先级队列存还没完成的任务项
		for (int i = n; i > 0; i--) {
			while (t[current] >= i && current < n) { //加入符合条件的作业项
				p1.push(node(t[current], v[current]));

				current++;
			}
			if (!p1.empty()) { //每过一天,完成一项任务
				p1.pop();
			}

		}
		int remains = 0;
		while (!p1.empty()) { //统计剩余的作业项
			remains += p1.top().v; //扣分
			p1.pop();
		}
		cout << remains << endl; //输出
	}

	return 0;
}

发布了16 篇原创文章 · 获赞 2 · 访问量 297

猜你喜欢

转载自blog.csdn.net/ziseon/article/details/104982465