动态规划问题(一)最大切分段数


动态规划问题(一)最大切分段数

问题描述

给你一段长为 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-2025 CODEPRJ.COM