需要木刻递归建议

时间:2015-04-12 05:24:13

标签: algorithm recursion dynamic-programming

您将获得长度为&n; n'的木材记录。日志上有'm'标记。必须在每个标记处切割日志。切割成本等于正在切割的原木的长度。给出这样的日志,确定最小的切割成本。

我的部分解决方案是使用递归: 当我按顺序在标记数组中,即从第0个切割到数组切割结束时,我能够得到成本。然而,当我们不按顺序切割时,即按照随机顺序切割时,我仍然不知道如何编写序列的代码,例如代码可以解释当切割不是顺序时的情况并且对所有这些情况采取最大值。

一种解决方案是对标记数组进行所有排列。为所有排列调用woodcut函数并取最大值,但这似乎是天真的方法。

有什么建议吗?

标记= [2,4](切割点)

int woodcut(length, cut_point, index){
    if (cut_point > length)
            return INFINITY
    first_half = cut_point;
    second_half = length - cut_point
    if (markings[index++] == exist) {
            if (next_cut_point > first)
                    cost = length + woodcut(second_half, next_cut_point-first)
            else    
                    cost = length + woodcut(first_half, next_cut_point)  
    } else if (index >= sizeof(markings))
            return cost;
}

http://www.careercup.com/question?id=5188262471663616

在查找答案并在一些慷慨的人的帮助下,我能够编写以下解决方案:

    #include <stdio.h>

    int min(int a, int b)
    {
            return a>b?b:a;
    }

    int min_cut(int first, int last, int size, int *cuts)
    {
            int i;
            unsigned int min_cost = 1U<<30;
            /* there are no cuts */
            if (size == 2)
                    return 0;
            /* there is only one cut between the end points */
            if (size == 3)
                    return last - first;
            /* cut at all the positions and take minimum of all */
            for (i=1;i<size;i++) {
                    if (cuts[i] > first && cuts[i] < last) {
                            int cost = last-first + min_cut(first, cuts[i], i+1, cuts) +
                                                    min_cut(cuts[i], last, size - i, cuts);
                            min_cost = min(cost, min_cost);
                    }
            }
            return min_cost;
    }

    int main()
    {
            int cuts[] = {0, 2, 4, 7, 10};
            int size = sizeof(cuts)/sizeof(cuts[0]);
            printf("%d", min_cut(cuts[0], cuts[size-1], size, cuts));
            return 0;
    }

3 个答案:

答案 0 :(得分:1)

方法A:

首先编写一个简单的递归函数,计算从i标记到j标记切割成碎片的最低成本。通过最小化所有可能的第一次削减成本以及削减两个侧面部件的最低成本来做到这一点。

记住此功能,以便它有效。

方法B: 计算一个值表,用于计算从i标记到j标记切割成块的最低成本。使用标记数ij的外循环是分开的,然后使用内部循环i然后进行第一次切割的可能位置的内部循环

两种方法都有效。两者都是O(m*m*m)我通常采用方法A.

答案 1 :(得分:0)

动态编程。复杂度O(m ^ 3)。 python中的解决方案。输入是标记位置的有序列表,最后一项是日志的长度:

def log_cut(m):
  def _log_cut(a, b):
    if mat[a][b]==None:
      s=0
      min_v=None
      for i in range(a+1, b):
         v=_log_cut(a, i)+_log_cut(i, b)
         if min_v==None or v<min_v:
           min_v=v
      if min_v!=None:
        s=min_v+m[b-1]
        if a>0:
          s-=m[a-1]
      mat[a][b]=s
    return mat[a][b]

  mat=[[None for i in range(len(m)+1)] for j in range(len(m)+1)]
  s=_log_cut(0, len(m))
  return s

答案 2 :(得分:-2)

这种情况类似于分而治之的排序。快速排序,例如:

  • 有一个分区步骤,需要在数组上进行线性传递,将其分成两个子数组。同样,削减日志的成本等于其长度。
  • 然后是递归步骤,其中递归地对每个子数组进行排序。类似地,您必须递归地继续剪切日志被剪切的两个部分,直到您切割所有标记。

当然,Quicksort在最佳情况下是O(n log n),当每个分区步骤(基本情况除外)将数组划分为两个几乎相同大小的子阵列时,就会发生这种情况。因此,您需要做的就是找到最接近中间的标记,&#34; cut&#34;那里的日志,并递归。