Dynamic Programming学习笔记 (14) - 剪彩带

147 阅读1分钟

剪彩带问题与最小硬币数问题基本类似,不同之处在于求解目标是最大值,其题面为:

给定一条彩带长度为N,将这条彩带按三种不同长度a,b,c剪开,问可以得到的最多彩带条数。

实例如下:

N = 7, a = 5, b, = 2, c = 5 
结果:2 
彩带长度为7,可以剪为两条,一条长度为2,另一条长度为5

DP表达式显而易见

F(k)
  = Integer.MIN_VALUE, k < 0
  = 0, k = 0
  = max of (1 + F(k - a), 1 + F(k - b), 1 + F(k - c))

F(k)返回的就是当彩带长度为k时,可以剪成的最多条数,其边界值在于当k<0时,返回一个极小值,因为无法剪出a,b,c中的任意一个。

Java代码如下

class Solution {
    public int maximumSegments(int n, int a, int b, int c) {
        int[] dp = new int[n + 1];

        for (int i = 1; i <= n; i++) {
            int max = 0;

            boolean cut = false;
            if (i >= a) {
                cut = true;
                max = Math.max(max, 1 + dp[i - a]);
            }
            if (i >= b) {
                cut = true;
                max = Math.max(max, 1 + dp[i - b]);
            }

            if (i >= c) {
                cut = true;
                max = Math.max(max, 1 + dp[i - c]);
            }

            if (cut) {
                dp[i] = max;
            } else {
                dp[i] = Integer.MIN_VALUE;
            }
        }

        return (dp[n] >= 0) ? dp[n] : 0;
    }
}