杆切割算法的替代方法(递归)

时间:2017-10-15 15:17:03

标签: algorithm dynamic-programming

在“算法导论”一书中,解决杆切割问题的天真方法可以通过以下重复来描述:

设q是从长度为n的杆获得的最大价格。

让数组价格[1..n]存储给定的价格。 price [i]是长度为i的棒的给定价格。

rodCut(int n)
{
    initialize q as q=INT_MIN

    for i=1 to n
        q=max(q,price[i]+rodCut(n-i))

    return q
}

如果我使用以下方法解决该怎么办:

rodCutv2(int n)
{
   if(n==0)
     return 0

    initialize q = price[n]

    for i = 1 to n/2
        q = max(q, rodCutv2(i) + rodCutv2(n-i))

    return q
}

这种做法是否正确?如果是,我们为什么一般使用第一个?为什么会更好?

注意: 我只关心解决这个问题的方法。我知道这个问题表现出最优的子结构和重叠的子问题,并且可以使用动态编程有效地解决。

3 个答案:

答案 0 :(得分:0)

第二个版本的问题是它没有使用价格数组。没有递归的基本情况所以它永远不会停止。即使你在n == 1时添加一个返回价格[i]的条件,它也总会将把杆切割成尺寸为1的碎片的结果。

答案 1 :(得分:0)

您的第二种方法绝对正确,其时间复杂度也与第一种相同。 在动态编程中,我们也可以采用相同的方法进行制表。这是我递归的解决方案:

int rodCut (int price[],int n){
      if(n<=0) return 0;
      int ans = price[n-1];
      for(int i=1; i<=n/2 ; ++i){
      ans=max(ans, (rodCut(price , i) + rodCut(price , n-i)));
      }
  return ans;
}

而且,动态编程解决方案:

int rodCut(int *price,int n){
   int ans[n+1];
   ans[0]=0;   // if length of rod is zero
   for(int i=1;i<=n;++i){
       int max_value=price[i-1];
    for(int j=1;j<=i/2;++j){
        max_value=max(max_value,ans[j]+ans[i-j]);
    }
     ans[i]=max_value;
   }
   return ans[n];
}

答案 2 :(得分:-1)

您的算法看起来几乎正确 - 当n为奇数时,您需要小心。

但是,它在时间复杂度方面也是指数级的 - 在每次调用rodCutv2时都会进行两次递归调用。第一种算法使用memoisation(price数组),因此避免多次计算同一事物,因此更快(它是多项式时间)。

编辑:实际上,第一种算法不正确!它永远不会在prices中存储值,但我怀疑这只是一个错字而非故意。