我只能想出一个蛮力的办法来解决这个问题。有兴趣看看AlgoSo社区会想出什么
给出一个arra
和一个整数x
(1<;x<;=len(a))。在不重新排序的情况下,将阵列划分为x个子阵列s1, s2....sx
,以使max(s1) + max(s2)....+ max(sx)
的总和是子阵列总和的所有可能组合中的最小值(参见下面的示例)。返回一个包含x-1索引的数组,其中包含发生拆分的索引i(不包括)
例如:
a = [10,30,40,20,50]
x = 2
return = [1]
将索引1处的数组拆分为[10]和[30,40,20,50]
将产生max([10]) + max([30,40,20,50]) = 60
,这是所有其他拆分数组方法中的最小值
其他可能的拆分-
如果你能将暴力组织成记忆化,那么暴力也没那么糟糕
该方法可以递归地进行左右分割,以确定最佳解决方案,将每个左侧前缀与最佳解决方案相结合,从而减少右侧分割的次数。由于这将多次计算同一个右侧拆分,因此内存化(将过去的结果保留在内存中以供重用)将使大多数探索分支短路
输出:
这是一个动态规划问题
首先建立以下数据结构
例如,在您的问题中,数据结构如下所示:
这可以通过简单的双循环创建。你从
[[(a[0], a[0], 0)]]
开始。要计算i, j
项,您必须查看在(i-1, j-1)
项之后启动一个新组,或者将当前元素添加到(i-1, j)
项中的最后一个组完成此操作后,从阵列的最后一个位置和所需的分割数开始。数据结构告诉您上一次拆分的位置,然后您转到该位置并向下拆分一次,以找到前一次拆分的位置。沿着饼干屑的痕迹往回走,你会发现所有的裂口
在您的示例中,
(len(a), x)
条目位于(4, 1)
,并且具有值(50, 60, 1)
。上一个条目位于(1, 0)
,其值为(10, 10, 0)
。我们忽略边界处的分裂,得到[1]
作为答案如果你想做
x=3
,那么你应该从(50, 100, 2)
开始,回到(40, 50, 1)
,然后到(10, 10, 0)
,得到[1, 2]
的答案为了使Max(sx)尽可能小,我们应该始终努力创建具有尽可能小的数字的子阵列。因此,只需将输入列表划分为具有最小可能值的单个元素列表:
相关问题 更多 >
编程相关推荐