题目描述
一个工厂有 m
条流水线,来并行完成 n
个独立的作业,该工厂设置了一个调度系统,在安排作业时,总是优先执行处理时间最短的作业。
现给定流水线个数 m
,需要完成的作业数 n
,每个作业的处理时间分别为 t1
,t2
…tn
。请你编程计算处理完所有作业的耗时为多少?
当 n
> m
时,首先处理时间短的 m
个作业进入流水线,其他的等待,当某个作业完成时,依次从剩余作业中取处理时间最短的进入处理。
输入描述
第一行为 2
个整数 (采用空格分隔),分别表示流水线个数 m
和作业数 n
;0 < m,n
< 100
第二行输入 n
个整数 (采用空格分隔) ,表示每个作业的处理时长 t1
,t2
…tn
。0 < t1,t2...tn
< 100。
注:保证输入都是合法的。
输出描述
输出处理完所有作业的总时长。
示例1
输入
3 5
8 4 3 2 10
输出
13
说明
- 先安排 2、3、4 的 3 个作业;
- 第一条流水线先完成作业,然后调度剩余时间最短的作业 8;
- 第二条流水线完成作业,然后调度剩余时间最短的作业 10;
- 总耗时就是第二条流水线完成作业的时间 13 (3 + 10 = 13)。
解析
本题考查贪心算法。
首先,我们可以将所有作业按照处理时间升序,这样我们顺序取出的作业,必然是剩余作业中处理时间最短的。
然后,我们顺序地取出作业,并将作业依次加入到 1~ m 序号的流水线中
假设作业处理时间 t1 ≤ t2 ≤ t3 … ≤ tn,那么依次加入到流水线的情况如下
其中 t1 最小,因此序号 1 的流水线首先空闲出来,然后加入 t[m+1] 作业
此时思考一个问题:下一个率先空闲出来的流水线是哪个?
因为,t[1] ≤ t[2] ≤ t[3] … ≤ t[m] ≤ t[m+1]
所以,t[2] - t[1] ≤ t[3] - t[1] ≤ … ≤ t[m] - t[1] < t[m+1]
进而推得:后续流水线会依次按照序号2、序号3、…序号m、序号1空闲出来
通过上面推理,我们可以知道,如果我们顺序地取出(按照处理时间升序后)作业,并依次加入到 1 ~ m 序号的流水线,那么流水线也会按照 1 ~ m 的序号顺序依次空闲出来。如下图,是 m 条流水线累计处理的作业情况
由于流水线是依次 1~m 空闲出来的,因此,最后一个作业落在哪条流水线上,则对应流水线就是最后完成的。
由于作业是按顺序依次加入到 1 ~ m 流水线的,因此,最后完成的流水线上的处理过的作业倒序依次是 t[n],t[n-m],t[n-2m],…,我们只需要累加这些作业时间,即为题解。
源码实现
C
#include <stdio.h>
#include <stdlib.h>
#define MAX_N 100
int cmp(const void *a, const void *b) {
return *((int *) a) - *((int *) b);
}
int main() {
int m, n;
scanf("%d %d", &m, &n);
int t[MAX_N];
for (int i = 0; i < n; i++) {
scanf("%d", &t[i]);
}
qsort(t, n, sizeof(t[0]), cmp);
int result = 0;
for (int i = n - 1; i >= 0; i -= m) {
result += t[i];
}
printf("%d", result);
return 0;
}
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
int m, n;
cin >> m >> n;
vector<int> t(n);
for (int i = 0; i < n; i++) {
cin >> t[i];
}
sort(t.begin(), t.end());
int result = 0;
for (int i = n - 1; i >= 0; i -= m) {
result += t[i];
}
cout << result;
return 0;
}
Java
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int[] t = new int[n];
for (int i = 0; i < n; i++) {
t[i] = sc.nextInt();
}
Arrays.sort(t);
int result = 0;
for (int i = n - 1; i >= 0; i -= m) {
result += t[i];
}
System.out.println(result);
}
}
Python
if __name__ == '__main__':
m, n = map(int, input().split())
t = list(map(int, input().split()))
t.sort()
result = 0
for i in range(n - 1, -1, -m):
result += t[i]
print(result)
JavaScript
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
const [m, n] = (await readline()).split(" ").map(Number);
const t = (await readline()).split(" ").map(Number);
t.sort((a, b) => a - b);
let result = 0;
for (let i = n - 1; i >= 0; i -= m) {
result += t[i];
}
console.log(result);
})();