剑指Offer: 剪绳子(Python语言实现)

给你一根长度为n的绳子,请把绳子剪成m段(m、n都是整数, n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m]。
请问k[0]*k[1]*...*k[m]可能的最大乘积是多少?

这里设置一个res列表来跟踪当前数字的最大乘积,那么后一个数字ni的最大乘积则为两边乘积的最大值,即max_value = max(res[nj)* res[ni-nj),其中nj∈[1, n//2+1]。运用动态规划解决问题的关键是具备从上到下分析问题、从下到上解决问题的能力。

应用动态规划求解的问题的特点:

  • 求一个问题的最优解,而且该问题能够分解成若干个子问题,并且子问题之间还有重叠的更小的子问题。

  • 分析能够把大问题分解成小问题,分解后的每个小问题也存在最优解,而把小问题的最优解组合起来能够得到整个问题的最优解。

  • 把大问题分解成若干个小问题,这些小问题之间还有相互重叠的更小的子问题。

  • 由于子问题在分解大问题的过程中重复出现,为了避免重复求解子问题,可以用从下往上的顺序先计算小问题的最优解并存储下来,再以此为基础求取大问题的最优解。从上往下分析问题,从下往上求解问题。

应用贪婪算法解决问题的时候,每一步都可以做出一个贪婪的选择,基于这个选择,确定能够得到最优解。

def max_product_after_cutting(n):
    if n < 2:
        return 0
    if n == 2:
        return 1
    if n == 3:
        return 2
    res = [0, 1, 2, 3]
    for ni in range(4, n+1):
        max_value = 0
        for nj in range(1, ni//2 + 1):
            current = res[nj] * res[ni-nj]
            if current > max_value:
                max_value = current
            else:
                break
        res.append(max_value)
    return res[-1]

此外,可以根据值的规律来求解。即当n>=5时,尽可能多地剪长度为3的绳子;当剩下的绳子长度为4时,把绳子剪成两段长度为2的绳子。也就是说,根据n % 3的值存在三种情况:

  • n % 3 == 2的时候,长度为3和为2的绳子数目分别为n // 3, 1

  • n % 3 == 1的时候,长度为3和为2的绳子数目分别为n // 3 - 1、 2

  • n % 3 == 0的时候,长度为3和为2的绳子数目分别为n // 3, 0

def max_product_after_cutting(n):
    if n < 2:
        return 0
    if n == 2:
        return 1
    if n == 3:
        return 2

    three = n // 3
    if n - three*3 == 1:
        three -= 1
    two = (n - three*3) // 2

    return pow(2, two) * pow(3, three)

(最近更新:2019年09月21日)

你可能感兴趣的:(PROGRAM)