我正在尝试解决以下练习(取自“算法设计手册”)
我们希望计算使用两根手指在标准按键电话上拨打给定 n 位数号码的最懒惰方式。我们假设两根手指从 * 和 # 键开始,并且手指从一个按钮移动到另一个按钮所需的努力与它们之间的欧几里得距离成正比。设计一个算法来计算拨号方法,该方法涉及移动手指的最小总距离,其中 k 是键盘上不同键的数量(对于标准电话,k = 16)。尝试使用 O(nk^3) 时间
首先,让 d=d1.d2....dn be the n-digit sequence
我提出的算法使用两个二维(nxk)数组 L,R
- L[a][b]:min cost to type the d[a]-digit with the left finger and having
the right finger at button b
- R[a][b]:same thing but with right and left instead.
为了填充这两个数组,我使用了两个几乎相同的递归函数(因此我只会为 L 发布一个)
首先,
- L[a+1][b]=L[a][b]+cost_from_d[a]_to_d[a+1]
也就是说,我们将右手手指放在按钮上,左手手指从 d[a] 移动到 d[a+1]
然后,如果 b==d[a](即用右拨的最后一位数字),那么还存在其他“正确”方式,以便通过将右手手指放在 d[ 上来用左手指键入 d[a+1] a] 按钮,然后将左手指从任何位置移动到 d[a+1]。
- L[a+1][b]=min(L[a+1][b],min(R[a][c]+cost_from_c_to_d[a+1]),)
为此,我首先找到最低成本,以便我们用左边拨 d[a+1] 用右边拨 d[a]。然后我将它与上子弹的值进行比较并保持最小值。
填充数组后,只需找到最小 L/R[n][whatever] 即可找到最小成本
对我来说,这段代码似乎是正确的。然而,考虑到时间复杂度只有 O(nk) 而不是 O(nk^3),我肯定犯了一些错误......
有没有人知道这些错误在哪里?