【问题标题】:Counting active tasks using start time and duration in C++在 C++ 中使用开始时间和持续时间计算活动任务
【发布时间】:2018-09-16 11:59:30
【问题描述】:

输入由一组按开始时间升序给出的任务组成,每个任务都有一个相关的持续时间。 第一行是任务数,例如

3
2 5
4 23
7 4

这意味着有 3 个任务。第一个从时间 2 开始,到 7 (2+5) 结束。第二个从 4 开始,到 27 结束。第三个从 7 开始,在 11 结束。 我们假设每个任务一旦准备好就开始,并且不需要等待处理器或其他任何东西释放。 这意味着我们可以跟踪活动任务的数量:

Time       #tasks
0 - 2        0
2 - 4        1
4 - 11       2
11 - 27      1

我需要找到 2 个数字:

  1. 任何给定时间的最大活动任务数(在本例中为 2)和
  2. 此处计算的整个持续时间的平均活动任务数为:

[ 0*(2-0) + 1*(4-2) + 2*(11-4) + 1*(27-11) ] / 27

为此, 我首先使用以下代码找到了所有任务结束的时间:

#include "stdio.h"
#include "stdlib.h"

typedef struct
{
    long int start;
    int dur;
} task;

int main()
{
    long int num_tasks, endtime;
    long int maxtime = 0;
    scanf("%ld",&num_tasks);
    task *t = new task[num_tasks];
    for (int i=0;i<num_tasks;i++)
    {
        scanf("%ld %d",&t[i].start,&t[i].dur);
        endtime = t[i].start + t[i].dur;
        if (endtime > maxtime)
            maxtime = endtime;
    }
    printf("%ld\n",maxtime);
}

这可以使用作为堆实现的优先级队列来完成吗?

【问题讨论】:

  • 这是 C 还是 C++?我看到你使用 C 头文件,但是 C++ 中的 new 关键字。
  • 这是 C++。文件格式为.cc。
  • 试试这个 -- 把所有的时间,不管是开始时间还是结束时间,都放在一个数组里,按时间升序对数组进行排序。然后遍历数组,如果时间是开始时间,则将计数加 1,如果时间是结束时间,则从计数中减去 1。计数的最大值是活动任务的最大数量。诀窍在于,哪个任务开始或哪个结束都无关紧要,即使它是问题的一部分,那也是无关紧要的信息。您只需要知道 a 任务已经开始并且 a 任务已经结束。
  • 当然可以使用优先队列来完成。但这不是最简单的解决方案,因此不应使用。最简单的解决方案将简单地对一组开始和结束时间进行排序,然后对其进行一次迭代以找到最大活动任务。这也会产生第一个开始时间和最后一个结束时间,因此是整个时间跨度。然后,您可以遍历所有任务以找到它们运行时间的总和并将其除以总时间跨度。排序是O(n log n),其他步骤都是O(n)的琐碎循环。

标签: c++ heap priority-queue event-driven


【解决方案1】:

您的问题相当广泛,所以我将只给您一个预告答案,希望能帮助您开始尝试回答问题的第一部分,但不一定是优化的解决方案。

在你的玩具输入中,你有:

2 5
4 23
7 4

因此,您可以计算任务的结束时间并将其存储在您拥有的结构数组中,而不是其持续时间,以供以后使用。这给出了这样的数组:

2 7
4 27
7 11

您的数组已经按开始时间排序(因为输入是按该顺序给出的),这很有用。如果需要,使用std::sort 对数组进行排序。

观察如何检查第一个任务的结束时间与其他任务的开始时间。通过正确的比较,您可以确定活动任务的数量以及第一个任务。检查第一个任务的结束时间是否大于第二个任务的开始时间,如果为真,则表示这两个任务在某个时刻同时处于活动状态。

然后,您将对第一个任务与第三个任务进行比较。之后,您将知道有多少任务与第一个任务相关。

之后,您将按照相同的步骤处理第二个任务,依此类推。

将所有这些放在代码中,我们得到:

#include "stdio.h"
#include "stdlib.h"
#include <algorithm>

typedef struct {
    int start;
    int dur;
    int end;
} task;

int compare (const task& a, const task& b) {
    return ( a.start < b.start );
}

int main() {
    int num_tasks;
    scanf("%d",&num_tasks);
    task *t = new task[num_tasks];
    for (int i=0;i<num_tasks;i++) {
        scanf("%d %d",&t[i].start,&t[i].dur);
        t[i].end = t[i].start + t[i].dur;
    }
    std::sort(t, t + num_tasks, compare);
    for (int i=0;i<num_tasks;i++) {
        printf("%d %d\n", t[i].start, t[i].end); 
    }
    int max_noOf_tasks = 0;
    for(int i = 0; i < num_tasks - 1; i++) {
        int noOf_tasks = 1;
        for(int j = i + 1; j < num_tasks; j++) {
            if(t[i].end > t[j].start)
                noOf_tasks++;
        }
        if(max_noOf_tasks < noOf_tasks)
            max_noOf_tasks = noOf_tasks;
    }
    printf("Max. number of active tasks: %d\n", max_noOf_tasks);
    delete [] t;
}

输出:

2 7
4 27
7 11
Max. number of active tasks: 2

现在,祝你问题的第二部分好运。


PS:因为这是 C++,你可以使用 std::vector 来存储你的结构,而不是一个普通的数组。这样你也可以避免动态内存分配,因为向量会自动为你处理。

【讨论】:

  • 这可以使用优先级队列作为事件模拟来完成吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
  • 1970-01-01
  • 2012-06-15
  • 2017-08-22
  • 2015-03-13
相关资源
最近更新 更多