问题在于:
我们有n天完成任务。我们每天可以完成一项任务。每个任务都有一个开始日期和结束日期。我们无法在开始日期之前开始任务,必须在结束日期之前完成。因此,给定开始日期的向量s
和结束日期的e
给出向量d
,如果存在,则d[i]
是您执行任务的日期{ {1}}。例如:
i
我们有一个可能的解决方案:
s = {1, 0, 1, 2, 0}
e = {2, 4, 2, 3, 1}
+--------+------------+----------+
| Task # | Start Date | End Date |
+--------+------------+----------+
| 0 | 1 | 2 |
| 1 | 0 | 4 |
| 2 | 1 | 2 |
| 3 | 2 | 3 |
| 4 | 0 | 1 |
+--------+------------+----------+
使用O(n ^ 2)创建算法是微不足道的。使用O(nlogn)创建算法也不算太糟糕。据推测,算法可以给出O(n)的解。那会是什么?
答案 0 :(得分:1)
当你不能使用时间时,请使用空间!您可以使用位向量表示任何一天打开的任务。在O(n)中创建一个“今天开始”数组。您还可以使用另一个也可以在O(n)中计算的位向量来表示最快结束的任务。然后最后,在O(n)中每天再次扫描,从那天开始添加任何任务,选择那天开放的最低编号的任务,优先考虑最快结束的任务。
using System.IO;
using System;
using System.Math;
class Program
{
static void Main()
{
int n = 5;
var s = new int[]{1, 0, 1, 2, 0};
var e = new int[]{2, 4, 2, 3, 1};
var sd = new int[n];
var ed = new int[n];
for (int task = 0; task < n; task++)
{
sd[s[task]] += (1 << task); // Start for task i
ed[e[task]] += (1 << task); // End for task i
}
int bits = 0;
// Track the earliest ending task
var ends = new int[n];
for (int day = n-1; day >= 0; day--)
{
if (ed[day] != 0) // task(s) ending today
{
// replace any tasks that have later end dates
bits = ed[day];
}
ends[day] = bits;
bits = bits ^ sd[day]; // remove any starting
}
var d = new int[n];
bits = 0;
for (int day = 0; day < n; day++)
{
bits |= sd[day]; // add any starting
int lowestBit;
if ((ends[day] != 0) && ((bits & ends[day]) != 0))
{
// Have early ending tasks to deal with
// and have not dealt with it yet
int tb = bits & ends[day];
lowestBit = tb & (-tb);
if (lowestBit == 0) throw new Exception("Fail");
}
else
{
lowestBit = bits & (-bits);
}
int task = (int)Math.Log(lowestBit, 2);
d[task] = day;
bits = bits - lowestBit; // remove task
}
Console.WriteLine(string.Join(", ", d));
}
}
在这种情况下的结果是:正如预期的那样,1,4,2,3,0。
答案 1 :(得分:0)
如果我错了,请纠正我,但我相信这些问题的名称将是 Interval Scheduling。
在您的帖子中,我假设您没有寻找最佳时间表,并且您只是想在O(n)中寻找任何解决方案。
这里的问题是排序将采用O(nlogn)并且计算也将采用O(nlogn)。您可以尝试一步完成:
定义V - &#39;时间的矢量&#39;为每项任务。
定义P - 在给定任务之前完成的任务向量。 即如果任务2在任务3之前完成,则[3] = 2。
当然,正如您所看到的,主要计算涉及找到P [j]。您始终采用最新结束的非重叠任务。
因此,找到P [i]。找到在第i个任务之前结束的任务。如果存在多个,请选择最后结束的那个。
定义M - 包含结果槽的向量。
算法: WIS(n)的
M[0] <- 0
for j <- 1 to n
do M[j] = max(wj + M[p(j)], M[j-1])
return M[n]
答案 2 :(得分:-1)
按结束日期,开始日期排序。然后按排序顺序处理数据,仅执行开始日期之后的任务。