将一个集合分成k组,使得移动次数最少

7
你有一组 n 个对象,给出它们的整数位置。一个 是在同一位置上的一组对象(不一定是该位置上的所有对象:可能有多个组在同一位置上)。这些对象可以向左或向右移动,并且目标是将这些对象移动以形成 k 个组,并且以最小距离移动来实现。
例如:
  • 初始位置为 [4,4,7],并且 k = 3:最小代价为0。
  • [4,4,7] 和 k = 2:最小代价为0。
  • [1,2,5,7] 和 k = 2:最小代价为1 + 2 = 3。
我一直在尝试使用贪婪方法(通过计算哪个移动最短)但这不起作用,因为每次移动都涉及两个可以任意移动的元素。我尚未能够制定动态规划方法,但我正在努力。

2
难道不是这样的吗:Set::[1,2,5,9]--->分成2组:::最小移动次数=1+3=4? - Klas Lindbäck
不完全是这样,位置2将有2个元素.....因此移动次数=1+3*2=7。 - Leopard
为什么你不能将5和1移动到2? - andrew cooke
4个回答

4
这个问题是K-中位数问题的一维实例,可以陈述如下。给定一组点x_1...x_n,将这些点划分为k个集合S_1...S_k,并选择k个位置y_1...y_k,使得所有x_i到其对应集合的位置y_f(i)的距离之和最小。由于中位数是绝对距离(即L_1范数)的种群最小化器, 因此每个位置y_j将成为相应集合S_j中元素x的中位数(因此称为k-中位数)。由于您正在查看整数值,存在这样的技术性问题:如果S_j包含偶数个元素,则中位数可能不是整数,但在这种情况下,选择中位数上面或下面的下一个整数将给出相同的绝对距离总和。
解决k-medians问题的标准启发式方法(以及相关且更常见的k-means问题)是迭代的,但这并不能保证产生最优甚至良好的解决方案。解决一般度量空间的k-medians问题是NP难的,并且寻找有效的k-medians近似算法是一个开放的研究问题。例如,谷歌搜索“k-medians近似”将会导致一堆给出近似方案的论文。 http://www.cis.upenn.edu/~sudipto/mypapers/kmedian_jcss.pdf http://graphics.stanford.edu/courses/cs468-06-winter/Papers/arr-clustering.pdf 在一维情况下,事情变得更容易,您可以使用动态规划方法。有关一维k-means问题的DP解决方案在this paper中描述,并且R的源代码可在here中获得。请参阅论文以获取详细信息,但是该想法基本上与@SajalJain提出的相同,并且可以轻松地适应解决k-medians问题而不是k-means。对于j<=k和m<=n,让D(j,m)表示x_1...x_m的最佳j-medians解决方案的成本,其中假定x_i按排序顺序排列。我们有循环关系。
D(j,m) = min (D(j-1,q) + Cost(x_{q+1},...,x_m)

其中q的范围从j-1到m-1,Cost等于中位数绝对距离之和。使用天真的O(n) Cost实现,会导致整个问题的O(n^3k) DP解决方案。然而,由于可以在恒定时间内更新成本,而不是每次都从头计算,因此可以将其改进为O(n^2k),利用排序序列的事实:

Cost(x_1,...,x_h) = Cost(x_2,...,x_h) + median(x_1...x_h)-x_1   if h is odd
Cost(x_1,...,x_h) = Cost(x_2,...,x_h) + median(x_2...x_h)-x_1   if h is even

更多细节请参见报告。除了成本函数的更新不同之外,k-medians的实现与k-means相同。 http://journal.r-project.org/archive/2011-2/RJournal_2011-2_Wang+Song.pdf


1

据我所知,问题是:

我们在一条线上有n个点。 我们想在该线上放置k个位置。我称它们为目的地。 将每个n个点移动到k个目的地中的一个,使距离之和最小。我称这个总和为总成本。 目的地可以重叠。

一个显而易见的事实是,对于每个点,我们应该寻找左侧和右侧最近的目的地,并选择最近的一个。

另一个重要的事实是,所有目的地都应该在点上。因为我们可以将它们向左或向右移动到达一个点,而不增加总距离。

根据这些事实,考虑以下DP解决方案:

DP [i] [j]表示前i个点所需的最小总成本,当我们只能使用j个目的地时,并且必须在第i个点上放置一个目的地。

要计算DP [i] [j],请先确定第i个点之前的目的地(我们有i个选择),并针对每个选择(例如第k个点)计算添加新点(第k个点)后所需的点之间的距离。将其与DP [k] [j-1]相加,并找到所有k的最小值。

初始状态(例如j = 1)和最终答案的计算留作练习!


0

任务0 - 将对象的位置按非递减顺序排序

我们定义'center'为对象的位置,它被移动到的位置。

现在我们有两个观察结果;

  1. 对于N个位置,“中心”将是最接近这些N个位置平均值的位置。例如,让1、3、6、10成为位置。那么平均值=5。最近的位置是6。因此,这些元素的中心是6。当所有元素需要分组为1组时,这给出了移动成本最小的位置。

  2. 将N个位置“最优地”分组为K组。当添加第N+1个对象时,它只会干扰第K个组,即前K-1个组将保持不变。

从这些观察结果中,我们建立了一种动态编程方法。

Let Cost[i][k] and Center[i][k] be two 2D arrays. 
Cost[i][k] = minimum cost when first 'i' objects are partitioned into 'k' groups
Center[i][k] stores the center of the 'i-th' object when Cost[i][k] is computed.

设{ L }是从i-L、i-L+1、..i-1中具有相同中心的元素。
(Center[i-L][k] = Center[i-L+1][k] = ... = Center[i-1][k])
这些是计算第i个元素时需要考虑的唯一对象(来自观察2)

现在

Cost[i][k] will be 
min(Cost[i-1][k-1] , Cost[i-L-1][k-1] + computecost(i-L, i-L+1, ... ,i))
Update Center[i-L ... i][k]

通过观察1,可以轻松地找到computecost()的中心。

时间复杂度:

Sorting O(NlogN)
Total Cost Computation Matrix = Total elements * Computecost = O(NK * N)
Total = O(NlogN + N*NK) = O(N*NK)

观察结果1是错误的。假设你有以下数据点:1, 2, 3, 4, 10。平均值是4,所以你会选择4。这会导致代价为3+2+1+6=12,但如果你选择了3,代价将是2+1+1+7=11。实际上,如果所有的点都要移动到一个位置,那么这个位置应该是一个左右两侧点数相同的位置。我在我的答案中进一步解释了这一点。 - Dave

0

让我们看一下k=1。

对于k=1且n为奇数,所有点都应该移动到中心点。对于k=1且n为偶数,所有点都应该移动到中心点之一或它们之间的任何位置。我所说的“中心”是指在两侧点数方面的中位数。

你可以看到这一点,因为如果你选择一个目标点x,它右边的点比左边的点多,那么向右移动一个新的目标点1会导致成本降低(除非右边恰好比左边多一个点且目标点是一个点,在这种情况下n为偶数且目标点在/在两个中心点之间)。

如果你的点已经排序,这是一个O(1)操作。如果没有,我认为它是O(n)(通过一个顺序统计算法)。

一旦你找到了所有点都要移动到的位置,找到成本就是O(n)。

因此,无论点是否排序,这都是O(n)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接