(C卷,200分)- 任务最优调度(Java & JS & Python & C)

题目描述

给定一个正整数数组表示待系统执行的任务列表,数组的每一个元素代表一个任务,元素的值表示该任务的类型。

请计算执行完所有任务所需的最短时间。

任务执行规则如下:

  1. 任务可以按任意顺序执行,且每个任务执行耗时间均为1个时间单位。
  2. 两个同类型的任务之间必须有长度为N个单位的冷却时间,比如N为2时,在时间K执行了类型3的任务,那么K+1和K+2两个时间不能执行类型3任务。
  3. 系统在任何一个单位时间内都可以执行一个任务,或者等待状态。

说明:数组最大长度为1000,数组最大值1000。

输入描述

  • 第一行记录一个用半角逗号分隔的数组,数组长度不超过1000,数组元素的值不超过1000,
  • 第二行记录任务冷却时间,N为正整数,N<=100。

输出描述

输出为执行完所有任务所需的最短时间。

用例

输入 2,2,2,3
2
输出 7
说明 时间1:执行类型2任务。
时间2:执行类型3的任务(因为冷却时间为2,所以时间2不能执行类型2的任务)。
时间3:系统等待(仍然在类型2的冷却时间)。
时间4:执行类型2任务。
时间5:系统等待。
时间6:系统等待。
时间7:执行类型2任务。
因此总共耗时7。

题目解析

本题考察贪心算法。

我的解题思路如下:

首先,我们统计出各种任务的数量,并找出数量最多的任务,比如题目用例中:

  • 任务2的数量是:3个
  • 任务3的数量是:1个

其中任务2的数量最多,有3个,我们假设k=3,那么完成所有任务所需时间至少为:

(k – 1) * (n + 1) + 1

画图示意如下:

其中n为冷却时间,k为最多任务的数量。

如果其他任务数量较少的话,可以直接在任务2的冷却时间中运行。比如题目用例运行图如下:

此时,总用时仍然为 (k – 1) * (n + 1) + 1。

理解了上面公式后,我们可以继续看下几种特殊情况:

1、数量最多的任务有多个,比如用例

2,2,2,3,3,3

2

此时画图示意如下:

此时至少用时为: (k – 1) * (n + 1) + 2

再比如用例

2,2,2,3,3,3,4,4,4

2

此时至少用时为: (k – 1) * (n + 1) + 3

可以发现,如果数量最多的任务有多个,假设为p个,则此时至少用时公式应该为:

 (k – 1) * (n + 1) + p

另外,还有一种特殊情况,如下用例

2,2,2,3,3,3,4,4,4,5,5,5

2

此时任务5有两种执行策略:

策略一如下:

 策略二如下:

很明显策略一更加省时。 因为策略一少了任务5的冷却时间。

可以发现,此时策略一的用时就是:总任务数量(每个任务执行耗时间均为1个时间单位)

因此:

  • 如果总任务数量 >=  (k – 1) * (n + 1) + p,则最少用时就是总任务数量本身。
  • 如果总任务数量 <  (k – 1) * (n + 1) + p,则最少用时就是 (k – 1) * (n + 1) + p

即取二者较大值。

JavaScript算法源码

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const lines = [];
rl.on("line", (line) => {
  lines.push(line);

  if (lines.length === 2) {
    const tasks = lines[0].split(",").map(Number);
    const n = lines[1] - 0;

    console.log(getResult(tasks, n));

    lines.length = 0;
  }
});

function getResult(tasks, n) {
  const cnts = {};

  for (let task of tasks) {
    cnts[task] ? cnts[task]++ : (cnts[task] = 1);
  }

  // k表示:最多任务的数量
  // 比如2,2,2,3, 其中任务2数量最多,有3个,则k = 3
  const k = Math.max(...Object.values(cnts));

  // p表示:数量为k的任务个数
  // 比如2,2,2,3,3,3,4, 其中数量为3的任务有2个,分别是任务2,任务3,则p=2
  let p = 0;

  for (let task in cnts) {
    if (cnts[task] == k) p++;
  }

  return Math.max((k - 1) * (n + 1) + p, tasks.length);
}

Java算法源码

import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;

public class Main {
  // 输入获取
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    int[] tasks = Arrays.stream(sc.next().split(",")).mapToInt(Integer::parseInt).toArray();
    int n = sc.nextInt();

    System.out.println(getResult(tasks, n));
  }

  // 算法入口
  public static int getResult(int[] tasks, int n) {
    HashMap<Integer, Integer> cnts = new HashMap<>();

    for (int task : tasks) {
      cnts.put(task, cnts.getOrDefault(task, 0) + 1);
    }

    // k表示:最多任务的数量
    // 比如2,2,2,3, 其中任务2数量最多,有3个,则k = 3
    int k = cnts.values().stream().max((a, b) -> a - b).orElse(0);

    // p表示:数量为k的任务个数
    // 比如2,2,2,3,3,3,4, 其中数量为3的任务有2个,分别是任务2,任务3,则p=2
    int p = 0;
    for (Integer task : cnts.keySet()) {
      if (cnts.get(task) == k) p++;
    }

    return Math.max((k - 1) * (n + 1) + p, tasks.length);
  }
}

Python算法源码

# 输入获取
tasks = list(map(int, input().split(",")))
n = int(input())


# 算法入口
def getResult():
    cnts = {}

    for task in tasks:
        cnts[task] = cnts.get(task, 0) + 1

    # k表示: 最多任务的数量
    # 比如2, 2, 2, 3, 其中任务2数量最多,有3个,则k = 3
    k = max(cnts.values())

    # p表示: 数量为k的任务个数
    # 比如2, 2, 2, 3, 3, 3, 4, 其中数量为3的任务有2个,分别是任务2,任务3,则p = 2
    p = 0
    for task in cnts:
        if cnts[task] == k:
            p += 1

    return max((k - 1) * (n + 1) + p, len(tasks))


# 算法调用
print(getResult())

C算法源码

#include <stdio.h>

#define MAX(a, b) ((a) > (b) ? (a) : (b))

#define MAX_SIZE 1001

int main() {
    // 一个正整数数组表示待系统执行的任务列表
    int tasks[MAX_SIZE];
    int tasks_size = 0;

    while (scanf("%d", &tasks[tasks_size++])) {
        if (getchar() != ',') break;
    }

    // 任务冷却时间
    int n;
    scanf("%d", &n);

    // k表示:最多任务的数量
    // 比如2,2,2,3, 其中任务2数量最多,有3个,则k = 3
    int k = 0;

    int cnts[MAX_SIZE] = {0};
    for (int i = 0; i < tasks_size; i++) {
        int task = tasks[i];
        cnts[task]++;
        k = MAX(k, cnts[task]);
    }

    // p表示:数量为k的任务个数
    // 比如2,2,2,3,3,3,4, 其中数量为3的任务有2个,分别是任务2,任务3,则p=2
    int p = 0;
    for (int i = 0; i < MAX_SIZE; i++) {
        if (cnts[i] == k) p++;
    }

    printf("%dn", MAX((k - 1) * (n + 1) + p, tasks_size));

    return 0;
}

免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?