题目
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和分值。
然后按照分值的大小给每个任务排序(放在一个队列中)。
最后每次从队列中取出分值最大的任务。由题可知,每天只能完成一个任务。所以,取出的任务可能有如下3种情况:
① ddl当天未被分配过任务,则把任务分配在ddl当天,例如图中分值为7、6、1的任务。
② ddl当天被分配过任务了,则把任务分配在离ddl前最近的一天,例如图中分值为5、4的任务。
③ ddl及之前的每一天都被分配任务了,则无法再分配取出来的任务,例如图中分值为3、2的任务。
以上即为分配任务的全过程。
之所以称为“贪心”,是因为每次都优先安排分值最大的任务。这个策略是可以得到最优解的。
代码
#include <iostream>
#include <queue>
#include <utility>
#define MAX 2000
using namespace std;
int T;
int N;
int ddl[MAX];
int score[MAX];
bool arrange[MAX];
struct task {
int score, ddl;
task(int theScore, int theDDL) { score = theScore; ddl = theDDL; }
bool operator < (const task& t)
{
if (score != t.score) return score < t.score;
}
};
struct cmp {
bool operator()(task t1, task t2)
{
if (t1.score != t2.score) return t1.score < t2.score;
}
};
// 分值越大的越往前排
priority_queue<task, vector<task>, cmp> q;
void printQueue(priority_queue<task, vector<task>, cmp>& q)
{
cout << "Queue:" << endl;
cout << "score ddl" << endl;
while (q.size() != 0) {
task t = q.top();
q.pop();
cout << t.score << " " << t.ddl << endl;
}
}
bool setTask(task& t)
{
int DDL = t.ddl;
for (int i = DDL; i > 0; i--) {
if (arrange[i] == false) {
arrange[i] = true;
return true;
}
}
return false;
}
void printArrange()
{
for (int i = 0; i < 2000; i++)
cout << arrange[i] << " ";
cout << endl;
}
void reset()
{
memset(arrange, false, sizeof(arrange));
}
int main()
{
#if(1)
cin >> T;
int maxDDL = 0;
for (int i = 0; i < T; i++) {
cin >> N;
for (int j = 0; j < N; j++) {
cin >> ddl[j];
if (maxDDL < ddl[j]) maxDDL = ddl[j];
}
for (int j = 0; j < N; j++) {
cin >> score[j];
}
for (int j = 0; j < N; j++) {
q.push(task(score[j], ddl[j]));
}
//printQueue(q);
int cnt = 0;
while (q.size() != 0) {
task t = q.top();
q.pop();
bool isSet = setTask(t);
if (!isSet) cnt += t.score;
}
cout << cnt << endl;
reset();
}
#endif
return 0;
}