动态规划-067-剪绳子

题目描述

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

示例

输入一个数n,意义见题面。(2 <= n <= 60)

输入: 8
输出: 18

分析

动态规划

如果要求一个问题的最优解,而且该问题能分成若干个子问题,整体问题的最优解依赖于子问题的最优解,可以考虑用动态规划解决。

动态规划一般是自顶向下思考,自底向上实现的,为了避免计算子问题时重复,可以将子问题的结果通过维护一张二维表来实现。

状态转移方程
f ( n ) = max ( f ( i ) f ( n i ) ) ,      i = 0 , 1 , . . . , n / / 2. f(n) = \max(f(i)*f(n-i)),~~~~i=0,1,...,n//2.

边界
f ( 0 ) = 0 f ( 1 ) = 1 f ( 2 ) = 2 f ( 3 ) = 3 f(0) = 0\\f(1)=1\\f(2)=2\\f(3)=3

时间复杂度: O( n 2 n^2 )
空间复杂度: O(n)

注意

  1. 这里的边界条件不是对应输入时的输出
  2. 当前阶段状态的值,与前面所有状态都有关系,所以只能通过维护二维表来实现,不能通过维护几个变量来实现。

贪心算法

首先, n 5 n\ge5 的时候,我们可以证明:
2 ( n 2 ) n    3 ( n 3 ) n    2(n-2)\ge n~~\\3(n-3)\ge n~~

也就是说,当绳子剩下的长度大于或者等于 5 的时候,我们就把它剪成长度为 3 或者 2 的绳子段。

此外:
3 ( n 3 ) 2 ( n 2 ) 3(n-3)\ge 2(n-2)
因此我们要尽量尽可能地多剪长度为 3 的绳子段。

时间复杂度: O(1)
空间复杂度: O(1)

代码

动态规划

# -*- coding:utf-8 -*-
class Solution:
    def cutRope(self, number):
        # write code here
        if number==2:
            return 1
        if number==3:
            return 2
        
        dp = [0, 1, 2, 3]

        for i in range(4, number+1):
            maxNum = 0
            for j in range(1,i//2+1):
                temp = dp[j]*dp[i-j]
                if maxNum<temp:
                    maxNum = temp
            dp.append(maxNum)
        return dp[number]

贪心算法

# -*- coding:utf-8 -*-
class Solution:
    def cutRope(self, number):
        # write code here
        if number<2:
            return 0
        if number==2:
            return 1
        if number==3:
            return 2
        if number==4:
            return 4
        
        timesOf3 = number//3    #多剪3
        if number-3*timesOf3 == 1:   #2*2>3*1
            timesOf3 -= 1
            
        timesOf2 = (number-3*timesOf3)//2  #剩下 4,或者 2 时剪 2
        
        return pow(3, timesOf3)*pow(2, timesOf2)
发布了219 篇原创文章 · 获赞 85 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/z_feng12489/article/details/103120449