From 4aa1511edefc5f8abe9e6be0d38e5e3c92af3505 Mon Sep 17 00:00:00 2001 From: CyC2018 Date: Fri, 30 Oct 2026 20:17:59 +0800 Subject: [PATCH] =?UTF-8?q?Update=2014.=20=E5=89=AA=E7=BB=B3=E5=AD=90.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 调整题目描述与边界说明,精简贪心策略的推导过程,补充动态规划解法的状态定义与状态转移说明。 --- notes/14. 剪绳子.md | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/notes/14. 剪绳子.md b/notes/14. 剪绳子.md index bc567ec8..d40cffd5 100644 --- a/notes/14. 剪绳子.md +++ b/notes/14. 剪绳子.md @@ -6,7 +6,7 @@ ## 题目描述 -把一根绳子剪成多段,并且使得每段的长度乘积最大。 +把一根长度为 n 的绳子剪成多段(至少剪一刀,n ≥ 2),每段长度为整数,求各段长度乘积的最大值。 ```text n = 2 @@ -20,21 +20,15 @@ return 36 (10 = 3 + 3 + 4) ### 贪心 -尽可能得多剪长度为 3 的绳子,并且不允许有长度为 1 的绳子出现。如果出现了,就从已经切好长度为 3 的绳子中拿出一段与长度为 1 的绳子重新组合,把它们切成两段长度为 2 的绳子。以下为证明过程。 +结论:尽可能多剪长度为 3 的段;剩下 1 时,把一个 3 + 1 改成 2 + 2;剩下 2 时,单独留一段 2。例如 n = 10 = 3 + 3 + 4,乘积 3 × 3 × 4 = 36。 -将绳子拆成 1 和 n-1,则 1(n-1)-n=-1\<0,即拆开后的乘积一定更小,所以不能出现长度为 1 的绳子。 +推导分三步: -将绳子拆成 2 和 n-2,则 2(n-2)-n = n-4,在 n\>=4 时这样拆开能得到的乘积会比不拆更大。 +- 不会出现长度为 1 的段:把 1 并到相邻的一段 x 上,乘积从 x 变为 x + 1,更大; +- 不会出现长度不小于 5 的段:把它拆成 2 和 x - 2,2(x - 2) - x = x - 4 \> 0,乘积更大。长度为 4 的段与 2 + 2 的乘积相同,可以看成两段 2,因此只剩下 2 和 3; +- 长度为 2 的段最多两段:三段 2 的总长与两段 3 相同,而 2 × 2 × 2 = 8 \< 3 × 3 = 9。 -将绳子拆成 3 和 n-3,则 3(n-3)-n = 2n-9,在 n\>=5 时效果更好。 - -将绳子拆成 4 和 n-4,因为 4=2\*2,因此效果和拆成 2 一样。 - -将绳子拆成 5 和 n-5,因为 5=2+3,而 5\<2\*3,所以不能出现 5 的绳子,而是尽可能拆成 2 和 3。 - -将绳子拆成 6 和 n-6,因为 6=3+3,而 6\<3\*3,所以不能出现 6 的绳子,而是拆成 3 和 3。这里 6 同样可以拆成 6=2+2+2,但是 3(n - 3) - 2(n - 2) = n - 5 \>= 0,在 n\>=5 的情况下将绳子拆成 3 比拆成 2 效果更好。 - -继续拆成更大的绳子可以发现都比拆成 2 和 3 的效果更差,因此只考虑将绳子拆成 2 和 3,并且优先拆成 3,当拆到绳子长度 n 等于 4 时,也就是出现 3+1,此时只能拆成 2+2。 +所以 n 除以 3 余 0 时全是 3;余 1 时最后是 2 + 2;余 2 时最后是一个 2。n = 2、3 时必须至少剪一刀,答案分别是 1 和 2,要单独处理。 ```java public int cuttingBamboo(int bamboo_len) { @@ -54,6 +48,8 @@ public int cuttingBamboo(int bamboo_len) { ### 动态规划 +dp[i] 表示长度为 i 的绳子剪过至少一刀后的最大乘积。枚举最后一段的长度 i - j,前面的 j 不再剪时乘积为 j × (i - j),继续剪时为 dp[j] × (i - j),取最大值。时间复杂度 O(N2)。 + ```java public int cuttingBamboo(int bamboo_len) { int[] dp = new int[bamboo_len + 1];