14- I. 剪绳子☆☆☆(动态规划)

动态规划从入门到精通(一)-入门篇

描述

给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m] 。请问 k[0]*k[1]*...*k[m] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
提示:

2 <= n <= 58

解析

动态规划五部曲

1. 判题题意是否为找出一个问题的最优解
2. 从上往下分析问题,大问题可以分解为子问题,子问题中还有更小的子问题
3. 从下往上分析问题 ,找出这些问题之间的关联(状态转移方程)
4. 讨论底层的边界问题
5. 解决问题(通常使用数组进行迭代求出最优解)

------1、判题题意是否为找出一个问题的最优解

看到字眼是“可能的最大乘积是多少”,判断是求最优解问题,可以用动态规划解决;

------2、从上往下分析问题,大问题可以分解为子问题,子问题中还有更小的子问题

题目中举了个例子:当绳子的长度为8时,我们把它剪成长度分别为2,3,3的三段,此时得到的最大乘积是18;我们可以从这里开始突破,把长度为8绳子的最大乘积分解为数个子问题,长度为8我们可以把它看成长度为1和7的绳子的和,或者长度 为2和6的绳子的和,或者长度为3和5的绳子的和and so on!
到这里,相信大家已经看到一丝真理了吧?

------3. 从下往上分析问题 ,找出这些问题之间的关联(状态转移方程)

在第二点时,我们已经从上到下分析问题了,现在我们要从下往上分析问题了。分析可知,
f(8) 的值就是f(1)*f(7),f(2)*f(6),f(3)*f(5),f(4)*f(4)它们之中的最小值,即f(8) = Max{f(1)*f(7),f(2)*f(6),f(3)*f(5),f(4)*f(4)}
只要知道f(1)到f(7)的值就能求出f(8);对于f(7),只要知道f(1)到f(6)的值就能求出f(6);对于f(6),只要知道f(1)到f(5)的值就能求出f(6);以些类推,我们只要知道前几个边界的值,就能一步步迭代出后续的结果!
状态转移方程: f(n)=Max{f(n-i)*f(i)} i={1,2,3,…,n/2}

------4. 讨论底层的边界问题

底层的边界问题说的就是最小的前几个数值的f(n)的值,本题中就是f(0)、f(1)、f(2)、f(3)的值
对于f(0),长度为0的绳子,没办法剪,没有意义
对于f(1),长度为1的绳子,没办法剪,设为1
对于f(2),长度为2的绳子,只有一种剪法,剪成两段长度为1的绳子,但剪后的乘积为1,比自身更小;如果不是求自身的值,要求乘积最大值的话就没必要剪。
对于f(3),长度为3的绳子,只有一种剪法,剪成两段长度为1和2的绳子,但剪后的乘积为2,比自身更小;如果不是求自身的值,要求乘积最大值的话也没必要剪。

代码

public static int cutting(int n) {
        //长度小于等等于1没办法剪
        if(n <= 1)
            return 0;
        //对于f(2),长度为2的绳子,只有一种剪法,剪成两段长度为1的绳子,剪后的乘积为1
        if(n == 2)
            return 1;
        //对于f(3),长度为3的绳子,只有一种剪法,剪成两段长度为1和2的绳子,但剪后的乘积为2
        if(n == 3)
            return 2;
        //数组用于存储绳子乘积最大值
        int value[] = new int[n + 1];
        value[0] = 0;
        value[1] = 1;
        //剪后的乘积为1,比自身更小;如果不是求自身的值,要求乘积最大值的话就没必要剪
        value[2] = 2;
        //剪后的乘积为2,比自身更小;如果不是求自身的值,要求乘积最大值的话也没必要剪
        value[3] = 3;
        //从f(4)开始迭代
        int max = 0;
        for(int i = 4;i <= n; i++) {
            max = 0;
            for(int j = 1;j <= i/2; j++) {
                max = Math.max(value[j] * value[i - j], max);
            }
            value[i] = max;
        }
        max = value[n];//绳子越长,当然剪出来的值越大
        return max;
    }

原文地址:https://www.cnblogs.com/fanguangdexiaoyuer/p/12342638.html

时间: 2024-10-10 17:09:39

14- I. 剪绳子☆☆☆(动态规划)的相关文章

面试题14:剪绳子

<?php header("content-type:text/html;charset=utf-8"); /* * 剪绳子 把一根绳子剪成多段,并且使得每段的长度乘积最大. P96 */ //动态规划 function integerBreak1($length){ if($length < 2){ return 0; } if($length == 2){ return 1; } if($length == 3){ return 2; } $products = arr

(python)剑指Offer(第二版)面试题14:剪绳子

题目 给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],…,k[m].请问k[0]k[1]…*k[m]可能的最大乘积是多少?例如,当绳子的长度为8时,我们把它剪成长度分别为2,3,3的三段,此时得到的最大乘积是18. 解题思想 动态规划(具体解法及思路见代码注释) 解题代码(python实现) # 题目一:给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1

【剑指offer】面试题 14. 剪绳子

面试题 14. 剪绳子 LeetCode 题目描述 给你一根长度为 n 的绳子,请把绳子剪成 m 段(m.n 都是整数,n>1 并且 m>1),每段绳子的长度记为 k[0],k[1],···,k[m].请问 k[0]xk[1]x···xk[m] 可能的最大乘积是多少?例如,当绳子的长度是 8 时,我们把它剪成长度分别为 2.3.3 的三段,此时得到的最大乘积是 18. Java 实现 class Solution { public int integerBreak(int n) { if (n

剪绳子问题(动态规划,贪婪,递归)

给你一根长度为n的绳子,请把绳子剪成m段(m.n都是整数,n>1并且m>1), 每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]xk[1]x...xk[m]可能的最大乘积是多少? 例如,当绳子的长度是8时,我们把它剪成长度分别为2.3.3的三段,此时得到的最大乘积是18. 思路 注意 当长度大于3 f[n]才能得到绳子的最大乘积 动态规划 特征 从上往下分析问题,从下往上求解问题; 求一个问题的最优解;(最大值或者最小值) 问题能够分解成若干个子问题,并且子问题之间还有重叠

【动态规划、贪心】剪绳子

题目 给你一根长度为n的绳子,请把绳子剪成整数长的m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]xk[1]x...xk[m]可能的最大乘积是多少? 例如,当绳子的长度是8时,我们把它剪成长度分别为2.3.3的三段,此时得到的最大乘积是18. 输入描述: 输入一个数n,意义见题面.(2 <= n <= 60) 示例1 输入 8 输出 18 示例2 输入 4 输出 4 解答 1,动态规划,从上往下分析问题,从下往上求解:T

剑指offer——15剪绳子

题目描述 给你一根长度为n的绳子,请把绳子剪成m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]xk[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2.3.3的三段,此时得到的最大乘积是18. 题解: 边界要注意一下,因为题目要求一定要分成至少两段,故,当n=1 ->1*0;   n=2  -> 1*1;   n=3   ->   2*1 两种方法进行求解 动态规划: 首

《剑指offer》第十四题(剪绳子)

// 面试题:剪绳子 // 题目:给你一根长度为n绳子,请把绳子剪成m段(m.n都是整数,n>1并且m≥1). // 每段的绳子的长度记为k[0].k[1].…….k[m].k[0]*k[1]*…*k[m]可能的最大乘 // 积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2.3.3的三段,此 // 时得到最大的乘积18. #include <iostream> #include <cmath> // ====================动态规划=========

剑指Offer对答如流系列 - 剪绳子

面试题13:剪绳子 题目描述 给你一根长度为n绳子,请把绳子剪成m段(m.n都是整数,n>1并且m>1).每段的绳子的长度记为k[0].k[1].--.k[m].k[0]*k[1]*-*k[m]可能的最大乘积是多少? 例如当绳子的长度是8时,我们把它剪成长度分别为2.3.3的三段,此时得到最大的乘积18. 问题分析 (1)思路一:动态规划 遇到问题,先分析问题,由分析的结果确定所运用的算法. 一般而言,我们都会在纸上动笔画画,罗列一些基本的情况. 题中说n>1并且m>1,那么 当n

剑指offer:剪绳子

题目:给定一根长度为n的绳子,请把绳子剪成m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],-,k[m].请问k[0] k[1] - *k[m]可能的最大乘积是多少? 例子:例如,当绳子的长度是8时,我们把它剪成长度分别为2.3.3的三段,此时得到的最大乘积是18. def cutRopeDP(length): """ 在剪绳子这个题目中,由于必须要剪一刀,因此会导致当所给的绳子长度是小于4的时候,剪完之后的长度 小于剪之前的长度.但