67 剪绳子
题目描述
给你一根长度为n的绳子,请把绳子剪成整数长度的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m]。请问k[0]xk[1]x...xk[m]可能的最大乘积是多少?
解题思路
方法一:动态规划
核心思想:dp[i]表示长度为i的绳子能得到的最大乘积。
方法二:数学方法
核心思想:尽可能多剪成长度为3的段。
时间复杂度:O(n)(DP)或 O(1)(数学) 空间复杂度:O(n)(DP)或 O(1)(数学)
Python 实现
python
# 方法一:动态规划
def max_product_cutting_dp(n):
"""
剪绳子的最大乘积(动态规划)
"""
if n <= 1:
return 0
if n == 2:
return 1
if n == 3:
return 2
dp = [0] * (n + 1)
dp[1] = 1
dp[2] = 2
dp[3] = 3
for i in range(4, n + 1):
max_product = 0
for j in range(1, i // 2 + 1):
max_product = max(max_product, dp[j] * dp[i - j])
dp[i] = max_product
return dp[n]
# 方法二:数学方法
def max_product_cutting(n):
"""
剪绳子的最大乘积(数学方法)
"""
if n <= 1:
return 0
if n == 2:
return 1
if n == 3:
return 2
# 尽可能多剪3
times_of_3 = n // 3
# 如果余数为1,退一个3
if n % 3 == 1:
times_of_3 -= 1
return 3 ** times_of_3 * 4
# 如果余数为2
elif n % 3 == 2:
return 3 ** times_of_3 * 2
return 3 ** times_of_3
# 测试代码
if __name__ == "__main__":
test_cases = [2, 3, 4, 5, 10]
for n in test_cases:
print(f"长度{n}, 最大乘积: {max_product_cutting(n)}")
# 输出:
# 长度2, 最大乘积: 1
# 长度3, 最大乘积: 2
# 长度4, 最大乘积: 4
# 长度5, 最大乘积: 6
# 长度10, 最大乘积: 36图解
数学方法分析:
- 当长度>=5时,剪出长度为3的段是最优的
- 因为3x2 > 5, 3x3 > 2x4
余数处理:
- 余数为0: 全部剪成3
- 余数为1: 3x1 < 2x2,所以退一个3,剪成2x2
- 余数为2: 直接剪成3...x2
示例: n=10
10 = 3 + 3 + 3 + 1
余数为1,退一个3
10 = 3 + 3 + 2 + 2
乘积 = 3 x 3 x 2 x 2 = 36