控制台log输出为何频频失踪?
wxss代码为何频频失效?
wxml布局为何乱作一团?
究竟是道德的沦丧?还是人性的缺失?
让我们一起来走跑进科学
前言
某工厂收到了n个产品的订单,这n个产品分别在AB两个车间加工并且必须先在A车间加工后才可以到B车间加工。某个产品在 AB两车间加工的时间分别为A,B。怎样安排这n个产品的加工顺序,才能使总的加工时间最短。这里所说的加工时间是指:从开始加工第一个产品到最后所有的产品都已在AB两车间加工完毕的时间
正文
这是一道经典的调度问题,可以使用贪心算法来解决。具体地,可以按照以下步骤进行:
- 将所有产品按照在A车间加工所需时间的升序排列。
- 依次取出排好序的产品,将它们加入一个队列中。
- 每次从队列中取出在B车间加工所需时间最小的产品进行加工,直到队列为空。
下面给出这个算法的证明:
设第i个产品在A车间加工所需时间为Ai,在B车间加工所需时间为Bi,总共有n个产品需要加工。设按照上述贪心算法得到的加工顺序为P1,P2,...,Pn。
假设存在一种比上述算法得到的加工顺序更优的加工顺序Q1,Q2,...,Qn。根据定义,Qi在A车间加工时必须先于Qi+1加工,因此可以将Q1,Q2,...,Qn分为若干个由若干个连续的产品组成的子序列,每个子序列中的产品在A车间加工时的加工时间是单调递增的。
现在考虑对于任意一个这样的子序列,它的加工时间必然不劣于按照贪心算法得到的加工顺序的加工时间。这是因为,在按照贪心算法得到的加工顺序中,这个子序列中的产品在A车间加工的时间是单调递增的,而在任意一个其他的加工顺序中,这个子序列中的产品的加工时间必然不小于按照贪心算法得到的加工顺序中这个子序列中产品的加工时间。因此,如果将所有这样的子序列的加工时间都考虑进来,按照贪心算法得到的加工顺序的加工时间必然不劣于任何其他的加工顺序的加工时间。
因此,按照贪心算法得到的加工顺序必然是使得总加工时间最短的加工顺序。
上代码
function shortestTime(products) {
// 按照 A 车间加工时间排序
products.sort((a, b) => a.A - b.A);
let time = 0; // 总加工时间
let available = []; // 可以进入 B 车间加工的产品
for (let i = 0; i < products.length; i++) {
// 将产品送到 A 车间加工
time += products[i].A;
// 将已经完成 A 车间加工的产品加入 available 数组
available.push(products[i]);
// 找到可以进入 B 车间加工的产品中,加工时间最短的那个
let minIndex = 0;
for (let j = 1; j < available.length; j++) {
if (available[j].B < available[minIndex].B) {
minIndex = j;
}
}
// 将产品送到 B 车间加工
time += available[minIndex].B;
// 从 available 数组中移除已经完成 B 车间加工的产品
available.splice(minIndex, 1);
}
return time;
}
// 测试代码
const products = [
{ A: 2, B: 3 },
{ A: 5, B: 6 },
{ A: 1, B: 2 },
{ A: 4, B: 5 },
];
console.log(shortestTime(products)); // 输出 18
总结
上面的代码中,我们定义了一个 shortestTime
函数来计算总的加工时间。函数接受一个产品数组作为参数,每个产品对象包含两个属性 A
和 B
,分别表示在 A 车间加工和在 B 车间加工的时间。
在函数内部,我们按照 A 车间加工时间对产品进行排序,然后依次取出每个产品,将它送到 A 车间加工。每次送到 B 车间加工时,我们选择已经完成 A 车间加工且加工时间最短的产品进行加工。最后计算整个加工过程的总时间并返回。