動態規划問題(一)最大切分段數


動態規划問題(一)最大切分段數

問題描述

給你一段長為 L 的木棒,現在有三種切分長度 p、q、r,你只能將這根木棒切成在這三種長度內的組合,求這根木棒最大能夠切成多少段。

比如說:現在一根長為 11 的木棒,可以切分的長度為 2、3、5,因此該木棒最多能夠被切成 5 段,分別是:{2、2、2、2、3}

解決思路

由於只能在候選的三個長度內進行組合,因此可以考慮將這根木棒遞歸地按照候選長度進行切分,然后得到最終的組合數。然而,在這里使用遞推地方式可能會更好一些。

解決方案:在每個長度位置檢測是否能夠加上對應的候選長度,如果能加上,那么就是能切分的段數加一,但是可能也會有其它的方案可以組合目標長度,因此需要對比得到最大值。

狀態轉換方程:

$$
f(n) = max(f(n - p), f(n - q), f(n - r)) + 1
$$

 

邊界分析:對於長度為 0 的木棒,不存在相對應的切分方法,因此它的組合數為 0。

實現

public class Solution {
   /**
    * 得到長度為 n 的木棒能夠按照候選的長度組合的最大元素個數
    *
    * @param n : 木棒的長度
    * @param x : 可切成的候選長度 p
    * @param y : 可切成的候選長度 q
    * @param z : 可切成的候選長度 r
    * @return : 能夠切分的最大段數
    */
   public static int maximizeCuts(int n, int x, int y, int z) {
       int[] dp = new int[n + 1];

       // 由於有的長度是無法在當前的候選長度集合中進行切分的,因此需要考慮跳過它
       for (int i = 1; i <= n; ++i)
           dp[i] = -1;

       // 邊界情況,長度為 0 的木棒對任何候選切分子集切分的段數都為 0
       dp[0] = 0;

       for (int i = 0; i <= n; ++i) {
           // 如果當前訪問的長度是無法由現有的組合子集組合,那那么就說明不能被切分,跳過它
           if (dp[i] == -1) continue;

           /*
               如果當前的長度加上備選的切割長度要小於總共的木棒長度,
               那么就可以將組個分割的子段長度加到現有的長度上,同時增加段數
               由於加上的長度結果可能由多種組合情況,因此要找到最大的組合段數
           */
           if (i + x <= n)
               dp[i + x] = Math.max(dp[i + x], dp[i] + 1);
           if (i + y <= n)
               dp[i + y] = Math.max(dp[i + y], dp[i] + 1);
           if (i + z <= n)
               dp[i + z] = Math.max(dp[i + z], dp[i] + 1);
      }

       // 如果目標段數不能由現有的組合段數組合而來,則返回 0
       if (dp[n] == -1) return 0;

       return dp[n];
  }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM