Title:ZJM 有 n 个作业,每个作业都有自己的 DDL,如果 ZJM 没有在 DDL 前做完这个作业,那么老师会扣掉这个作业的全部平时分。
所以 ZJM 想知道如何安排做作业的顺序,才能尽可能少扣一点分。
Input:输入包含T个测试用例。输入的第一行是单个整数T,为测试用例的数量。
每个测试用例以一个正整数N开头(1<=N<=1000),表示作业的数量。
然后两行。第一行包含N个整数,表示DDL,下一行包含N个整数,表示扣的分。
output:对于每个测试用例,您应该输出最小的总降低分数,每个测试用例一行。
样例:
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
分析:
- 总分减去所得的分数即为扣掉的分数。故该题转换成求最大的得分。
- 从最后一天往前进行遍历,枚举每一天,给每一天安排任务。
- 假设最后一天为maxddl,现在是第x天,从所有t=x(即ddl是第x天)的deadline中,选一个分数最大的安排在第x天,若没有t=x(即ddl是第x天)的deadline,那么就从t属于(x,maxddl]且还未被完成的deadline中选择一个分数最大的安排在第x天。
- 具体实现:
以
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4为例
总结:该题关键在于每个deadline完成所需时间都是一致的,故优先考虑价值最高的任务。而从后往前遍历,则保证了对其他deadline的影响最小。
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
#define range 1010
int T = 0, n = 0, ans = 0, all = 0, maxddl = 0;
queue<int> work[range];
priority_queue<int> q;
int ddl[range];
void fun()
{
for (int i = maxddl; i > 0; i--)
{
while (!work[i].empty())
{
q.push(work[i].front());
work[i].pop();
}
if (!q.empty())
{
ans += q.top();
q.pop();
}
}
}
int main()
{
int tddl, tp;
cin >> T;
while (T > 0)
{
priority_queue<int> empty;
swap(empty, q);
all = 0;
ans = 0;
maxddl = 0;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> ddl[i];
if (ddl[i] > maxddl)
maxddl = ddl[i];
}
for (int i = 0; i < n; i++)
{
cin >> tp;
all += tp;
work[ddl[i]].push(tp);
}
fun();
cout << all - ans << endl;
T--;
}
}