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

给你一根长度为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]才能得到绳子的最大乘积

动态规划

特征
从上往下分析问题,从下往上求解问题;

  • 求一个问题的最优解;(最大值或者最小值)
  • 问题能够分解成若干个子问题,并且子问题之间还有重叠的更小的子问题
  • 分解后的小问题也存在最优解,如果把小问题的最优解组合起来能够得到整个问题的最优解,就可以使用动态规划
实现
public int cutRope(int target) {
    //排除特殊情况
    if (target < 2) {
        return 0;
    }
    if (target == 2) {
        return 1;
    }
    if (target == 3) {
        return 2;
    }
    int[] products = new int[target + 1];
    products[0] = 0;
    products[1] = 1;
    products[2] = 2;
    products[3] = 3;
    for (int i = 4; i <= target; i++) {
        int max = 0;
        for (int j = 1; j <= i / 2; j++) {
            int product = products[j] * products[i - j];
            max = Math.max(max, product);
        }
        products[i] = max;
    }
    return products[target];
}

贪婪

  • 由于是乘法,那么除了1以外越多数相乘,得到的结果就越大。
  • 因此从2开始考虑。但是都分成2的话必然会有奇数分成包含1的段数,因为1相当于浪费了一个乘数,所以如果最后剩1的时候我们应该将他变为3. 因此得到分成的段数长度为2,3是最好的。
  • 又因为 2 * 2 * 2 < 3 * 3 说明3个2都不如2个3 ,因此应该让3 相对来说比2 多。
  • 于是让该数对3相除,余数如果为2,则分为 1个2 ,N个3 为最优解,如果余数为1,则应分为2个2 ,N-1 个3 为最优解
实现
public int cutRope(int target) {
    //排除特殊情况
    if (target < 2) {
        return 0;
    }
    if (target == 2) {
        return 1;
    }
    if (target == 3) {
        return 2;
    }
    int timesOf3 = target / 3;
    if (target - timesOf3 * 3 == 1) {
        timesOf3--;
    }
    int timesOf2 = (target - timesOf3 * 3) / 2;
    int result = (int) (Math.pow(3, timesOf3) * Math.pow(2, timesOf2));
    return result;
}

递归

虽然动态规划比递归不知高到那里去,因为递归有很多的重复求解情况
但是,我看互联网上,剪绳子好像没有递归的解法,于是...就当看个玩

思路

f(n)=max(f(i)*f(n-i)) 0<i<n

实现
public int cutRope03(int target) {
    if (target < 2) {
        return 0;
    }
    if (target == 2) {
        return 1;
    }
    if (target == 3) {
        return 2;
    }
    int max = 0;
    for (int i = 1; i <= target/2; i++) {
        max = Math.max(cutRope03Core(i) * cutRope03Core(target - i), max);
    }
    return max;
}

private int cutRope03Core(int target) {
    if (target < 4) {
        return target;
    }
    int max = 0;
    for (int i = 1; i <= target/2; i++) {
        max = Math.max(cutRope03Core(i) * cutRope03Core(target - i), max);
    }
    return max;
}

原文地址:https://www.cnblogs.com/aiguozou/p/11576036.html

时间: 2024-11-09 09:29:59

剪绳子问题(动态规划,贪婪,递归)的相关文章

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

题目 给你一根长度为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

面试题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

《剑指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——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对答如流系列 - 剪绳子

面试题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

POJ1141 Brackets Sequence (dp动态规划,递归)

本文出自:http://blog.csdn.net/svitter 原题:http://poj.org/problem?id=1141 题意:输出添加括号最少,并且使其匹配的串. 题解: dp [ i ] [ j ] 表示添加括号的个数, pos[ i][ j ] 表示 i , j 中哪个位置分开,使得两部分分别匹配. pos [ i ][ j ] 为-1的时候,说明i, j 括号匹配. 初始值置dp [ i ] [ i ]  = 1; 如果只有一个括号,那么匹配结果必然是差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. def cutRopeDP(length): """ 在剪绳子这个题目中,由于必须要剪一刀,因此会导致当所给的绳子长度是小于4的时候,剪完之后的长度 小于剪之前的长度.但

【剑指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