我有以下问题:给定一个时间间隔列表和一个整数k
,是否有值<= k
赋值给间隔,使得没有两个重叠的间隔具有相同的值?是否有多项式算法来解决这个问题?我认为可以通过动态编程来解决,但我无法提出解决方案。
答案 0 :(得分:4)
你有k
台机器和一堆工作(间隔),每个工作都有一个开始和结束时间。每个作业将在其时间间隔内占用一台机器。你想知道你是否可以处理所有的工作。
当一份工作进来时,分配给哪台机器并不重要,只有有一台未占用的机器。同样,哪些机器被占用并不重要,只有正在运行的作业。机器1上的工作在2小时内完成,与机器3上的工作相同,工作在2小时内完成;无论哪种方式,你都有一台机器在接下来的两个小时内占用。
您的决定毫无意义。在任何时候,都会有一系列工作正在运行以及一些未占用的计算机。这一切都很重要。
考虑到这一点,在多项式时间内完成工作非常容易。只需按左端点对间隔进行排序,然后一次性完成,贪婪地为每个间隔分配任何适合的值。如何跟踪哪些机器被占用将影响您的运行时间,但几乎任何跟踪方法仍需要多项式时间。
答案 1 :(得分:2)
这可以通过一个简单的贪婪算法和两个堆栈来解决:一个是间隔/整数对(最初为空),另一个是整数(最初用0
填充到k
)。
按开始时间排序间隔并迭代它们。对于每个区间,首先迭代堆栈对并在每个区间内弹出一个结束时间,该结束时间在当前区间之前。开始时间。当弹出间隔时,将关联的整数推回到整数堆栈中。然后,弹出整数堆栈的一个整数,并将其与对堆栈上的当前事件一起推送。
如果整数堆栈在任何时候用完,问题就无法解决。解决方案是将它们推入堆栈时的间隔/整数对。
没有最大k
的替代解决方案也很容易:如果整数堆栈为空,则增加k
并使用它。
如果按结束时间使用优先级队列来存储间隔/整数对,则在最坏的情况下,此算法应为O(n log n)。
答案 2 :(得分:2)
虽然没有给出证明,但是Wikipedia article区间图提到了一个结果,表明考虑左边界非递减顺序的间隔并贪婪地指定最低可能的颜色会产生最佳结果。
显然,可以在以下教科书中找到更详细的讨论。
Cormen,Thomas H。; Leiserson,Charles E。; Rivest,Ronald L。;斯坦因, Clifford(2001)[1990]。算法简介(第2版)。 MIT 按和McGraw-Hill。国际标准书号0-262-03293-7。
请注意,根据图表着色的Wikipedia article,区间图的色数恰好是clique数。
答案 3 :(得分:0)
您的问题等同于找到可以在O(nlogn)
中完成的最大交叉间隔数。
证明:假设对于一组间隔S
,k
是来自S
的最大交叉间隔数。显然,我们必须使用至少k
个数字来进行有效的分配。现在我们需要证明k
已足够。让我们按S
的升序顺序迭代。每次我们打开一个新的间隔时,我们从未使用的数字集中选择一个数字,每次我们关闭一个间隔时,我们将数字放回到该集合。显然,一组k
数字足以使其发挥作用。
c ++的代码:
bool canAssign(const std::vector<std::pair<int, int>> &intervals, int k)
{
const int left = 0, right = 1;
std::vector<std::pair<int, int>> ends;
for (const auto &interval: intervals)
{
ends.emplace_back(interval.first, left);
ends.emplace_back(interval.second, right);
}
std::sort(ends.begin(), ends.end());
int maxStack = 0, stack = 0;
for (const auto &end: ends)
{
if (end.second == left)
++stack;
else
--stack;
maxStack = std::max(maxStack, stack);
}
return maxStack <= k;
}