我们有 N 个工作,编号为 1 到 N。对于每个活动,让 Ti 表示完成工作所需的天数。在开始为工作 i 工作之前每延迟一天,就会造成 Li 的损失。
我们需要找到一个序列来完成工作,以便将整体损失降至最低。我们一次只能从事一项工作。
如果多个这样的解决方案是可能的,那么我们需要给出字典序最小的排列(即字典顺序中最早的)。
例子:
Input : L = {3, 1, 2, 4} and
T = {4, 1000, 2, 5}
Output : 3, 4, 1, 2
Explanation: We should first complete
job 3, then jobs 4, 1, 2 respectively.
Input : L = {1, 2, 3, 5, 6}
T = {2, 4, 1, 3, 2}
Output : 3, 5, 4, 1, 2
Explanation: We should complete jobs
3, 5, 4, 1 and then 2 in this order.
让我们考虑两个极端情况,并从中推导出一般情况的解决方案。
- 所有作业的完成时间相同,即所有 i 的 Ti = k。由于所有作业都需要相同的时间来完成,因此我们应该首先选择损失(Li)大的作业。我们应该选择损失最大的工作,并尽早完成它们。
因此这是一个贪心算法。仅基于 Li 按降序对作业进行排序。 - 所有工作都有相同的惩罚。由于所有工作都有相同的惩罚,我们将首先执行那些需要较少时间来完成的工作。这将最小化总延迟,因此也最小化发生的总损失。
这也是一种贪心算法。根据 Ti 按升序对作业进行排序。或者我们也可以按 1/Ti 的降序排序。从上述案例中,我们不难看出,我们不应仅根据 Li 或 Ti 对作业进行排序。相反,我们应该根据 Li/Ti 的比率降序对作业进行排序。
如果我们对工作进行稳定排序,我们可以获得字典上最小的工作排列。一个稳定排序的例子是归并排序。
为了获得最准确的结果,请避免将 Li 除以 Ti。相反,比较两个比率,如分数。要比较 a/b 和 c/d,请比较 ad 和 bc。
// CPP program to minimize loss using stable sort. #include
#include #include using namespace std; #define all(c) c.begin(), c.end() // Each job is represented as a pair of int and pair. // This is done to provide implementation simplicity // so that we can use functions provided by algorithm // header typedef pair > job; // compare function is given so that we can specify // how to compare a pair of jobs bool cmp_pair(job a, job b) { int a_Li, a_Ti, b_Li, b_Ti; a_Li = a.second.first; a_Ti = a.second.second; b_Li = b.second.first; b_Ti = b.second.second; // To compare a/b and c/d, compare ad and bc return (a_Li * b_Ti) > (b_Li * a_Ti); } void printOptimal(int L[], int T[], int N) { vector list; // (Job Index, Si, Ti) for (int i = 0; i < N; i++) { int t = T[i]; int l = L[i]; // Each element is: (Job Index, (Li, Ti) ) list.push_back(make_pair(i + 1, make_pair(l, t))); } stable_sort(all(list), cmp_pair); // traverse the list and print job numbers cout << "Job numbers in optimal sequence are\n"; for (int i = 0; i < N; i++) cout << list[i].first << " "; } // Driver code int main() { int L[] = { 1, 2, 3, 5, 6 }; int T[] = { 2, 4, 1, 3, 2 }; int N = sizeof(L) / sizeof(L[0]); printOptimal(L, T, N); return 0; } 输出:
Job numbers in optimal sequence are 3 5 4 1 2
时间复杂度:O(N log N)
空间复杂度:O(N)如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。