杆切割 - 递归

时间:2017-05-28 17:11:07

标签: c++ c recursion

问题:http://www.geeksforgeeks.org/dynamic-programming-set-13-cutting-a-rod/

我的代码位于:http://ideone.com/HGXk3t

我尝试解决递归问题,但得到了意想不到的结果。 对于棒切割问题,我最多接受两次相同递归函数的调用:一个使用该索引,另一个不使用该索引的价格。 但答案不是应该是什么。 提前谢谢。

#include<stdio.h>

// A utility function to get the maximum of two integers
int max(int a, int b) { return (a > b)? a : b;}

/* Returns the best obtainable price for a rod of length n and
   price[] as prices of different pieces */
int cutRod(int price[], int n, int i)
{
    if(n<1 || i==0)
        return 0;

    return max(price[i-1] + cutRod(price,n-(i+1),i), cutRod(price,n,i-1));
}

/* Driver program to test above functions */
int main()
{
    int arr[] = {17, 17, 1};
    int size = sizeof(arr)/sizeof(arr[0]);
    printf("Maximum Obtainable Value is %d\n", cutRod(arr, size, size));
    getchar();
    return 0;
}

3 个答案:

答案 0 :(得分:1)

您的递归通话在下降/上升期间丢失信息。

在您的回访期间,看到它在数组中向后工作,它所做的就是返回最大可能值并忽略剩余的卡盘。

假设这个极端的例子是 echo "<!DOCTYPE html PUBLIC '-//W3 ... <input type='text' id='theField' name='to' value='"; echo $email_str echo "' style='height:15px; width:65 ... </html>"; n=2;。理想情况下,答案是200.

在第一次通话时,返回值为p=[100,1];。 第一个调用return max(1,cutRod(2,2-1));的第二个参数忽略了杆的第二个卡盘,并在递归调用时开始检查杆的第一个卡盘。

通话的第二级提供cutRod(2,2-1)

第三个电话max(100,cutRod(2,1-1));,所以i=0

检查递归调用的级别,我们只取这对值的最大值:

cutRod(2,0) = 0

所以100最终成为最大值,而不是返回200

level 3 = 0 //0 comes from cutRod(2,1-1)
level 2 = max(100,0) //100 comes from cutRod(2,2-1): 0 comes from cutRod(2,1-1)
level 1 = max(1,100) //1 comes from p[2-1]: 100 comes from max(100,0)

我不推荐这种多次递归调用方式来解决这种动态编程问题。相反,这是在中找到的例子 算法简介, 第三版Cormen,Leiserson,Rivest,Stein pg.363

return max(price[i-1] + cutRod(price,n-(i+1),i), cutRod(price,n,i-1));

没有循环的递归解决方案 *需要分析

#include <limits.h>
//p is the price array
//n is the initial size of the array or 'rod'
int cutRod(int p[],int n){
  if(n == 0){
    return 0;
  }
  int q = INT_MIN;
  for(int i = 1; i<=n; i++){
    q = max(q,p[i-1]+cutRod(p,n-i));
  }
  return q;
}

答案 1 :(得分:0)

杆切割问题基本上表明,如果我们可以切割成离散增量的杆,以及那些不连续尺寸的杆的价格,我们如何切割杆以使我们获得最佳的整体价格。在你的例子中,你传递了一个大小为3 {17,17,1}的数组,根据我们的问题陈述,它说一块1号尺寸的杆子可以工作17个单位,一块2号尺寸的价值17个单位,尺寸3的一块价值1个单位。显然,你的例子的最佳解决方案是将杆切成单个单元并将其出售。您提供的链接中的示例具有如下价格表:{1,5,8,9,10,17,17,20}。对此的解决方案不太明显,需要更细致的方法来解决它。这种情况是递归解决方案显示其价值的情况。

您的解决方案似乎试图解决此问题的天真递归版本,我们不会考虑您提供的链接中讨论的重叠子问题。要以天真的方式解决这个问题,您需要检查所有子问题并返回其最大结果,然后将它们组合起来以找到全局最大值。例如,对于尺寸为8的杆,您需要找到尺寸为7,6,5的杆的最大返回价格......并将这些选项组合起来以找到全局最大值。您的解决方案找不到并组合这些选项,这就是为什么您没有得到正确的结果。检查和组合此问题的所有子问题的最直观方法是执行类似此伪代码的操作:

def cutRod(arr price[], int n)
   if(n <= 0)
     return 0;
   int max_val = -inf //set maximum value to negative infinity
   for(int i = 0; i<n; ++i)
     max_val = max(max_val, price[i] + cutRod(price, n-i-1));
   return max_val;

这基本上是作为您提供的链接中的天真示例给出的代码。它的作用是在给定尺寸的杆上循环所有可能的价格选项,以及通过以给定价格销售所述杆尺寸所返回的值,以及杆的其余部分可能的最大价格。对于他们的示例{1,5,8,9,10,17,17,20},代码将首先找到位置1处的杆切割的最大价格,因此您使用cutRod(价格,7)添加价格[0] )。这找到了你可以出售7号杆的最高价格,即18(17和1),并将价格[0]加到那里,返回19.这个过程继续,直到你找到所有的最大值子问题,最终为22.

正如您所看到的,在这个例子中,我们基本上检查了我们的杆切割方案的所有可能的合理选项,在上面的代码中,您只检查了一些选项,其中许多选项实际上并不销售整个杆。 / p>

请注意,此解决方案远非针对此问题的最有效解决方案。它没有考虑重叠的子问题,这些子问题在您提供的链接中得到解决。

答案 2 :(得分:0)

#Python 解决方案 它会给出 TLE 错误,所以一定要使用记忆的解决方案。

class Solution:
    def __init__(self):
        self.ans=0
    def cutRod(self, price, n):
        l=[]
        for i in range(1,n+1):
            l.append(i)
        rod_l=n
        self.solve(l,price,n,rod_l)
        return self.ans
    
    def solve(self,l,price,n,rod_l):
        if n==0 or rod_l<1:
            return 0
        if l[n-1]<=rod_l:
            self.ans=max(self.solve(l,price,n-1,rod_l),price[n-1]+self.solve(l,price,n,rod_l-l[n-1]))
            return self.ans
        else:
            self.ans=self.solve(l,price,n-1,rod_l)
            return self.ans