三分区(动态编程示例)

时间:2015-12-27 15:41:35

标签: c arrays dynamic-programming partitioning

我有一个int数组,其中包含{47, 94, 79, 90, 89, 14, 82, 92}等数字。必须将数组分成三个子数组,以便每个数组的总和尽可能小,即最小。我认为它值得用递归来解决,但是这个方法让我感到厌烦,我还想到在初始数组上使用qsort然后将它除去"贪婪"但它始终不起作用(例如取最低和最高数字等)。

例如,上面的数字将分为: 1) {94, 90, 14} 2) {92, 89} 3) {82, 79, 47}

这里第三个数组包含最高的最小和,即208。数字的顺序无关紧要。问题是如何将数字公平地分成三组,以便它们形成最低的总和。我是否必须测试所有可能性?

1 个答案:

答案 0 :(得分:0)

可以使用动态编程对所描述的问题进行建模。我们可以按如下方式定义状态空间。

v[i,t1,t2] := minimal load in partition 3 attainable for items
              in {0,...,i} where the total load in partition 1
              is exactly t1 and the total load in t2 is exactly t2
              if such a load exists and positive infinity otherwise

对于州空间,i位于{0,...n}t1t2位于{0,...,P},其中P是总和项目的上限,是客观价值的上限,以n*smax为界,其中smax是输入中出现的最大值。

我们获得了以下递归关系,其中案例基本上依赖于迭代选择分配给它的分区的每个元素,其中s_i表示i项的大小。

v[i,t1,t2] = min { v[i-1,t1-s_i,t2],
                   v[i-1,t1,t2-s_i],
                   v[i-1,t1,t2] + s_i }

最小表达式中的第一项对应于将项i分配到分区3中,第二种情况对应于将项i分配到分区2中,第三种情况对应于分配项{{1}填充状态空间后,可以通过评估以下表达式获得所需的结果(即分区的最小最大负载)。

i

在上面的最大表达式中,Result = min { max { t1, t2, v[n,t1,t2] : t1, t2 in {0,...,P} } } 将对应于分区1中的负载,t1将对应于分区2中的负载和 状态值t2对应于分区3中的负载。草绘算法的运行时间可以由v[n,t1,t2]限制,O(n^3*smax)是伪多项式运行时绑定。如果另外需要将项目最佳分配到分区中,则必须使用回溯或辅助数据结构。

请注意,为其中一个相同的分区赋予特殊作用似乎是假的,因为其负载是状态的值,而其他分区的负载用于状态空间的轴。此外,乍一看,国家的价值似乎可以轻易获得,因为它只是剩余的总负荷

sum_{j=1}^{i} s_i - ( t1 + t2 )

但情况并非如此,因为上述数量仅确定分区3中的负载(如果实际存在这样的分配);在状态空间的定义中,正无穷大的使用表明这种分配不存在。

该方法非常类似于here,第12页ff所描述的方法。总之,所描述的问题可以被视为调度问题,即最小化3个相同并行机器的完工时间。在所谓的three-field notation中,问题表示为P3||Cmax,这意味着机器的数量不是输入的一部分,而是固定的。