给定一个整数列表l
,我如何将其划分为两个列表a
和b
,使得d(a,b)=abs(sum(a)-sum(b))
最小。我知道这个问题是NP完全的,所以我正在寻找一个伪多项式时间算法,即O(c*n)
其中c=sum(l map abs)
。我看了维基百科,但是算法是把它分成精确的两半,这是我要找的一个特例...
编辑:为了澄清,我正在寻找确切的分区a
和b
,而不仅仅是产生的最小差异d(a,b)
概括地说,什么是伪多项式时间算法,将一个n
数字列表划分成k
组g1,g2... gk
,使得(max(S)-min(S))。abs
S=[和(g1),和(g2),...和(gk)]
我的第一个想法是:
当然,这并不能保证给你最好的结果,但是你可以用列表中最大整数的大小来限制它给你的结果
你可以将其表述为0/1整数线性规划优化问题。设Wi为第i个数,并设席是0/1个变量,表示Wi是否在第一个集合中。然后你想最小化sum(xi-wi)-sum((1-xi)wi)以
苏姆(xi wi)
而且所有的席都是0或1。有很多关于优化0/1线性规划求解器的研究。对于大和W,这可能是对O(Wn)伪多项式时间算法的改进,因为W因子很可怕。
一个简单的、平凡的、仍然是伪多项式的解决方案是使用现有的解决方案来子集sum,并将sum(array)/2
重复到0(并返回找到的第一个)。
这个解决方案的复杂度将是O(W^2*n)
,其中W
是数组的总和。
伪代码:
for cand from sum(array)/2 to 0 descending:
subset <- subsetSumSolver(array,cand)
if subset != null:
return subset
上面的函数将返回最大的子集,该子集小于/等于sum(array)/2
,另一部分是返回子集的补码。
然而,子集和的动态规划应该足够了。
回想一下公式是:
f(0,i) = true
f(x,0) = false | x != 0
f(x,i) = f(x-arr[i],i-1) OR f(x,i-1)
在构建矩阵时,如果您输入sum(array)/2,则上面的命令实际上创建的每一行的值都低于初始值x
,这基本上是所有值。
生成DP矩阵后,只需找到x
的最大值,这样f(x, n)=true
,这就是你能得到的最佳分区。
这种情况下的复杂度是O(Wn)
我有一个值(整数)的列表,我想拆分成B非空子列表,而不改变它们的初始顺序。目标是调整文本的大小,使其适合定义的区域。 每个子列表将有一个与之关联的指标:其值的总和。我想最小化所有子列表中最大和和最小和之间的差异DIFF。这将允许我将文本分成几乎相同数量的文本行。 编辑 正如所建议的那样,它还可以最小化最大和,因为这将导致最小化文本行的最大长度。 示例: 给定列表L={2,3,4,5,6}和B=2。
给定一个正整数的矩阵(非正方形),其中同一行上的所有元素都是可置换的,问题是最小化列的最大和和最小和之间的差异。 例如 答案是2。 我试着天真地对它进行分类(合并)
我有一个元素数组< code>[(A1,B1),...,(An,Bn)](都是正浮点和Bi 毫无疑问,我可以尝试所有这些方法,并选择一个给出最小和的方法(这将给出正确的结果O(n!)). 我尝试将总和更改为并尝试使用贪婪算法,该算法在每个步骤上获取最大的Ai元素(这不会产生正确的结果)。 现在,当我看最新的方程时,我觉得这里我看到了最优子结构,因此我必须使用动态编程,但我无法找出正确的方向。有什么
我有一个数组(自然数),我需要构建一个贪婪的算法,找到1…n的排列(i1,…in),使和最小:。 当然,我可以尝试所有这些,并选择一个给出最小的总和(这将在O(n!)中给出正确的结果)。 我贪婪的选择是按降序选择数字,但我不知道如何证明这是有效的。 页(page的缩写)这只是为了学习和训练,我不能“贪婪地”思考
问题内容: 我有一个清单: 如何将带有动态间隙的最近值分组,并创建这样的元组,最快的方法是什么?: 问题答案: 喜欢 首先,我们计算顺序元素之间的平均差异,然后将差异小于平均值的元素分组在一起。
输入是实数x1、x2、…、x2n的序列。我们想把这些数字配对成n对。对于第i对(i=1,2,…,n),让Si表示该对中的数字之和。(例如,如果将x(2i−1) 并且x2i作为第i对,Si=x(2i−1) x2i)。我们希望将这些数字配对,以使Maxi[Si]最小化。设计一个贪婪算法来解决这个问题。 这就是问题所在;我的解决方案是简单地对数字进行排序,并将前一个元素与后一个元素配对,加一个/减一个索