【问题标题】:C recursive function to find minimumC递归函数找到最小值
【发布时间】:2012-11-28 20:37:55
【问题描述】:

我正在写一个程序:

例如输入是 5(它不仅可以是 5)数字,我在数组中读取数据:1, 2, 3, 4, 5。我可以从这个数组中选择一些元素(不是第一个或最后一个),例如3,然后我删除数组中的这个数字,并将 sum (最初是 0 )相乘的从左到右的元素与从右到右的元素相乘(在这种情况下是指 2*4 )。结果数组是1, 2, 4, 5,然后我一次又一次地这样做,直到元素数等于2(正好是1 and 5,因为我们不能删除这些数字)。

例如:(其中 A、B、C、D 是一对数字 1 和 2、2 和 3 等。)

 A B C D
1 2 3 4 5

删除元素的顺序有 6 种可能的组合(并在 sum 中添加左右乘法):

A (B (C D))
A ((B C) D)
(A B) (C D)
(A (B C)) D
((A B) C) D
A (B (C D))

目标是找到最小的总和!有两种解决方法,一些聪明的算法或对每个组合使用递归,然后选择最小的一个。谁能给我一个提示如何编写这样的递归,从哪里开始编写(或者可能是一些聪明的算法)。天呐

【问题讨论】:

  • 我不明白为什么会有五种组合。您可以删除除结束元素之外的所有元素,并且可以按任何顺序进行删除。对于一个包含 5 个元素的列表,这将使 (5-2)! = 6 种组合。 (它们是:(2, 3, 4), (2, 4, 3), (3, 2, 4), (3, 4, 2), (4, 2, 3), (4, 3, 2 ).) 在您的示例中,您永远不会将 1 和 2 配对,因为它们之间没有任何东西可以删除!
  • 能否请您在您的示例中添加操作A (B (C D))
  • 按升序对列表进行排序,并继续删除左起第 2 个位置的元素 - 在您的示例中按该顺序删除 2、3、4。总和不会低于这个。
  • 可能只是我 - 但我已经阅读了 3 次问题,但无法理解您到底想要什么。最小子集的总和不是空的吗?你能正式定义你到底在追求什么吗? :|
  • @amit - 我相信 OP 希望以最小化结果总和的顺序删除所有内部元素。 (当然,这样的命令可能不止一个。)

标签: c algorithm


【解决方案1】:

递归回溯解决方案相当简单(伪代码):

def solve (list): 
    if list.length == 2:
        return 0
    ans = INFINITY
    for each interior element:
        remove element from list
        ans = min(ans, leftelement * rightelement + solve(list))
        place element back in original position in list
    return ans

但是,该算法的速度不足以处理非平凡数据集,因为它的运行时间是阶乘 (O(n!))。优化递归解决方案的常用方法是dynamic programming。让我们提出子状态:

dp[a][b]: minimum cost to reduce array[a .. b] to two elements on the edge
          (array[a] and array[b])

基本情况是dp[i][i + 1], i = {0 .. size - 1)(两个相邻元素)。由于没有要删除的内部元素,因此此子状态设置为 0。

对于所有其他情况dp[a][b] 其中b - a >= 2,我们可以通过删除任何在[a + 1, b - 1] 之间索引的内部元素来划分array[a .. b]。如果我们在元素 i 上划分子数组,则成本为dp[a][i] + dp[i][b] + array[a] * array[b]。我们希望最小化每个子状态的成本,因此我们将对所有可能的划分元素取这些值中的最小值。最后的答案就是dp[0][size - 1]

由于有 O(n^2) 子状态,每个子状态平均需要考虑 O(n) 划分元素,因此总运行时间为三次 (O(n ^ 3)),应该在合理的时间内运行中小型数据集。

【讨论】:

  • 该算法的运行时间下限为 O(n!)。我想你误读了这个问题。
  • 是的,由于递归性质,第一个算法是 O(n!)。但是,第二种算法将其减少到立方时间。底部的运行时分析是针对改进的动态规划解决方案。
  • 它对我有用,尤其是动态编程方法,tnx 很多!
猜你喜欢
  • 2015-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 2020-07-03
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多