这是一道很有趣的题目,我们要在只能进行全部复制和粘贴操作的情况下做最少的操作次数,题目如下所示:
这道题目从表面上看,这道题目似乎没有思路,我们应该在什么时候复制什么时候进行粘贴,这些细节都是很难处理的。所以我们可以不考虑这些细节,直接用动态规划的思想来分析这道题目,那么这道题目的核心就是求解出动态规划的递推方程。
首先我们想一下,在最普通的情况下,我们一个个地粘贴单字母‘A’,需要
i
−
1
i-1
i−1次粘贴和
1
1
1次复制,就是
i
i
i次操作。在我们可以整除某个约数
j
j
j 的时候,我们需要进行粘贴操作
(
i
−
j
)
/
j
(i-j)/j
(i−j)/j 次,加上一次复制全部的操作,那就是
(
i
−
j
)
/
j
+
1
(i-j)/j+1
(i−j)/j+1 操作。所以我们可以得到动态规划的递推方程是:
d
p
[
i
]
=
m
i
n
(
d
p
[
i
]
,
d
p
[
j
]
+
(
i
−
j
)
/
j
+
1
)
dp[i] = min(dp[i], dp[j]+(i-j)/j+1)
dp[i]=min(dp[i],dp[j]+(i−j)/j+1)
初始状态:
d
p
[
1
]
=
0
dp[1] = 0
dp[1]=0
有了初始状态和动态规划的递推方程之后,我们可以写出代码:
class Solution(object):
def minSteps(self, n):
"""
:type n: int
:rtype: int
"""
if n == 1 or n == 0:
return 0
dp = [_ for _ in range(n+1)]
dp[1] = 0
for i in range(2, n+1):
dp[i] = i
for j in range(1, i):
if i % j == 0:
dp[i] = min(dp[i], dp[j] + (i - j)/j + 1)
return dp[n]
所以,在这种细节难以分析的题目中,我们可以第一时间考虑用动态规划的思想来解决此类问题,重要的是我们要推导出动态规划的递推方程,这样的问题就可以迎刃而解了。