我会尝试用数学语言解释这个问题
假设我有一组项X = {x_1, x_2, ..., x_n}
。 X
的每个项目都属于其中一个集合S_1, S_2, ..., S_5
。我认为X
的所有子集都包含5个项目:
{x_i1, x_i2, ..., xi5}
因此x_i1
属于S_1
,......,x_i5
属于S_5
。
一些子集被认为是正确的,一些被认为是不正确的。如果子集不包含冲突项,则认为该子集是正确的。我有一个函数f1来判断一对项目是否冲突
我还有一个函数f2,它可以比较这些正确的子集,并说出哪个子集更好(它们可能也相同)。
我需要找到最好的不冲突的子集。
Algo我用过:
我构建了所有子集,丢弃了不正确的子集。然后我使用f2作为排序函数对正确的子集进行了排序,并采用了第一个最佳子集(我使用了快速排序算法)。只要存在大量子集,此过程就会花费不足的时间。
在时间消耗方面有更好的方法吗?
已更新
让我们将x_i看作是整数端点的间隔。如果2个间隔不相交,则f1返回true,否则返回false。 f2比较子集中间隔的总长度。
答案 0 :(得分:1)
如果没有进一步限定域和评估函数,可以通过将SAT减少到它来轻松地将此问题显示为NP-Complete(即,如果S_1,...,S_5为{true,false},则f2 = 1公式为fullfiled,如果不是则为0)。因此,在这种情况下,即使不考虑f1,你也没有运气。
如果您对f1和f1的实际结构有更多了解,那么您可能会有更多的运气。看看Constrait Satisfaction Problems,找出f1和f2结构中要查找的内容。
答案 1 :(得分:1)
让我们将x_i看作是整数端点的间隔。如果2个间隔不相交,则f1返回true,否则返回false。 f2比较子集中间隔的总长度。
如果我理解正确,这意味着我们可以从X为每个x_i分配一个值(它的长度)。那么就不需要在每个可能的解决方案/子集上评估f2。
最小的5 x_i不太可能构成最佳子集。根据实际数据,最佳子集可能是5个最大间隔。所以我建议按值排序X.一般的想法是从最高的x开始并尝试添加更多的x(最高的第一个)直到你有5个非重叠。在产生所有可能子集的一小部分(当然取决于具体问题)之前,您很可能会找到最佳子集。但在最坏的情况下,这并不比你的解决方案快。
答案 2 :(得分:1)
如果我们将条件从每个S_i中取出一个x,则此问题等效于区间图中的最大权重独立集(即,在顶点中的图中查找成对未连接顶点的最大权重集表示间隔,如果相应的间隔重叠,则连接顶点)。这个问题可以在多项式时间内解决。这里的版本也有每个顶点的颜色,所选的顶点需要具有所有不同的颜色。我不知道如何在多项式时间内解决这个问题,但你可以利用没有太多颜色的事实:制作一个动态编程表T [C,x],其中C是一组颜色,x是位置间隔的终点。 T [C,x]应包含您可以从| C |获得的最大权重C中颜色的间隔位于x的左侧。然后,您可以从左到右填写表格。这应该是可行的,因为只有2 ^ 5 = 32个颜色集。
答案 3 :(得分:1)
如果我对你的问题的理解是正确的,我有一个应该是好的解决方案: 所以我从我理解的开始
each Integer is actually an interval from I1 to I2 and a Set is a
combination of such intervals. A Set is correct if none of the intervals
are intersecting and Set1>Set2 if the sum of Intervals in S1> sum of Intervals in S2.
所以我在这种情况下所做的就是这些方面的事情。
在比较间隔以确定它们是否相交时,请执行此操作。
a)按起点顺序对间隔进行排序
b)比较连续间隔的第一个终点和起始点的终点以确定重叠。保持一个名为gap的整数,如果2个区间的开始和结束不与它们的差异重叠增量差距。
这将通过执行Endpoint(lastI)-Startpoint(firstI) - Gap自动获得集合中的间隔总和。
=>如果你只需要最好的,你可以拿一个变量max并保持比较集合。
=>如果您需要top5或其他内容,请按照以下步骤操作,否则请跳过。
只要得到总和并且设置正确,就将总和添加到5个元素的“MinHeap”中。前5个元素将按原样运行。基本上你正在跟踪前5个元素。当一个新集合小于堆的最小值“Do Nothing并忽略此集合,因为它小于前5个集合”时,当集合大于min(意味着它在前5个中)时替换min然后将元素向下筛选,将前5的最小值保持在顶部。这将始终保持堆中的前5个元素。
现在您已经拥有前5个元素,您可以通过5个弹出轻松确定最佳元素。 :)
注意:如果区间是随机顺序,它将进入O(n ^ 2)解决方案,然后每个比较将再次有4个if语句来检查重叠位置。您可以在O(nlogn)中对间隔进行排序,然后通过列表一次以确定重叠(nlogn + n = nlogn),同时获得前5个集合。这可以改善您的表现和时间。
答案 4 :(得分:1)
此问题是最大加权区间调度算法的变体。 DP算法的多项式复杂度为O(N*log(N))
,O(N)
空间用于天真问题,O(2^G * N * logn(N))
复杂度为O(2^G * N)
空间用于此变异问题,其中G
, N
表示组/子集的总数(此处为5)&间隔分别。
如果x_i不表示间隔,则问题出在NP中,其他解决方案已经证明了这一点。
首先让我解释一下最大加权区间调度的动态规划解决方案,然后解决变异问题。
start(i)
,end(i)
,weight(i)
分别为间隔i
的起点,终点,间隔长度。1, 2, ... N
。next(i)
代表与区间i
不重叠的下一个区间。S(i)
定义为仅考虑作业i, i+1, ... N
的最大加权间隔。S(1)
是解决方案,它会考虑来自1,2,... N
的所有作业并返回最大加权间隔。
S(i)
此解决方案的复杂性为S(i) = weight(i) if(i==N) // last job
= max(weight(i)+S(next(i)), S(i+1)
。 O(N*log(N) + N)
用于查找所有作业的N*log(N)
,next(i)
用于解决子问题。空间为N
,用于保存子问题解决方案。
现在,让我们解决这个问题的变化。
O(N)
,start(i)
,end(i)
,weight(i)
分别为间隔subset(i)
的起点,终点,间隔长度,子集。i
。1, 2, ... N
代表与区间next(i)
不重叠的下一个区间。i
定义为最大加权区间,只考虑作业S(i, pending)
和i, i+1, ... N
是一个子集列表,我们必须从中选择一个区间。pending
是解决方案,它会考虑所有作业S(1, {S_1,...S_5})
,为每个1,...N
选择一个时间间隔并返回最大加权时间间隔。
S_1,...S_5
请注意,我可能错过了一些基本情况。
此算法的复杂性为S(i)
,S(i, pending) = 0 if(pending==empty_set) // possible combination
= -inf if(i==N && pending!={group(i)}) // incorrect combination
= S(i+1, pending) if(group(i) not element of pending)
= max(weight(i)+S(next(i), pending-group(i)),
S(i+1, pending)
空间。 O(2^G * N * logn(N))
表示子问题的大小。
作为估算,对于O(2^G * N)
的较小值和2^G * N
的较高值,此算法运行得非常快。对于中等值G<=10
,N>=100000
也应该低,以使此算法收敛。对于G>=20
的高值,算法不会收敛。
答案 5 :(得分:0)
我没有得到答案,因为你提出了非常抽象的问题,但我会给你一个想法。
尝试思考multiThreading。例如,您可以使用有限数量的线程创建线程池。然后找到一个递归解决方案,并在你潜入时为每个循环开始新的任务。
我说,因为你可以将这个问题分解为许多小任务,因为你的算法会更好。
在数学上思考问题!
答案 6 :(得分:0)
考虑使用查找表来优化f1的时间。考虑将您发现的子集插入到合并排序列表中,而不是最后快速排序。如果域很小且有限,则可以通过填充稀疏数组来实现一些非常快速的合并排序。