我无法理解这一点:
假设我得到了一个数字9.我想知道拆分所需的最小步骤,以便没有数字大于3。
我一直认为最有效的方法是将每个循环减半。 所以,9 - > 4,5 - > 2,2,5 - > 2,2,2,3总共3个步骤。但是,我刚刚意识到了一种更聪明的方式:9 - > 3,6 - > 3,3,3只是两步......
经过一些研究,步数实际上是(n-1)/ target,其中target = 3在我的例子中。
有人可以向我解释一下这种行为吗?
答案 0 :(得分:3)
如果我们想将长度为L
的长棍切成不大于S
的尺寸,我们需要ceiling(L/S)
件。每次我们进行新的切割时,我们都会将碎片数量增加1.无论切割的顺序是什么,只要在哪里。例如,如果我们想要将长度为10的棒分成2或更小的块:
-------------------
0 1 2 3 4 5 6 7 8 9 10
我们应该在以下地方剪掉它:
---|---|---|---|---
0 1 2 3 4 5 6 7 8 9 10
任何削减顺序都可以,只要这些是削减。另一方面,如果我们开始把它分成两半:
---------|---------
0 1 2 3 4 5 6 7 8 9 10
我们做了一个不是最佳解决方案的削减,我们浪费了我们的时间。
答案 1 :(得分:1)
我真的很喜欢@ user2357112解释为什么减少一半不是正确的第一步,但我也喜欢代数,你可以用归纳证明ceil(n / target) - 1
是最优的。
首先让我们证明您始终可以ceil(n / target) - 1
步骤。
如果n <= target
,显然不需要步骤,那么公式有效。假设n > target
。将n
拆分为target
和n - target
(1步)。通过归纳,n - target
可以在ceil((n - target)/target) - 1
步骤中拆分。因此,步骤总数为
1 + ceil((n - target) / target) - 1
= 1 + ceil(n / target) - target/target - 1
= ceil(n / target) - 1.
现在让我们证明你不能在少于ceil(n / target) - 1
步骤的情况下做到这一点。如果n <= target
,这很明显。假设n > target
,第一步是n -> a + b
。通过归纳,a
至少需要ceil(a / target) - 1
步,而b
至少需要ceil(b / target) - 1
步。因此,所需的最小步骤数至少为
1 + ceil(a / target) - 1 + ceil(b / target) - 1
>= ceil((a + b) / target) - 1 using ceil(x) + ceil(y) >= ceil(x + y)
= ceil(n / target) - 1 using a + b = n
答案 2 :(得分:0)
每个n都可以被认为是首先放在队列中的\ lfloor n / target \ rfloor目标元素的优先级队列,以及一个值为n%target的元素。每次从队列中删除元素时,都会将其放回队列中。删除除最后一个元素之外的所有元素:您已经清除了\ lfloor(n-1)/ target \ rfloor元素。如果最后一个元素小于或等于目标,我们就完成了。如果它大于目标,我们就会产生矛盾。所以,在\ lfloor(n-1)/ target \ rfloor步骤之后,我们有一个只包含小于或等于target的元素的队列。