📜  使用动态编程以给定的操作将N转换为M(1)

📅  最后修改于: 2023-12-03 15:06:55.343000             🧑  作者: Mango

使用动态编程以给定的操作将N转换为M

动态编程是一种优化算法,它将问题分解为子问题,并使用记忆化技术以更快地解决问题。在给定的操作中将N转换为M可以使用动态编程实现。这个问题可以用DP的方式解决,可以通过将目标值M逐个减小,然后尽可能使M与N相似(即具有相同数量的各个数字)。你可以跟着以下步骤实现。

步骤
  1. 创建二维数组dp[M + 1][N + 1]。在这个数组中,dp[i][j]表示将i转换为j的最少步数。
  2. 使用两个嵌套循环遍历dp数组。外部循环应该从1到M,内部循环应该从1到N。
  3. 如果当前i等于j, dp[i][j]等于0,因为它本身相等。
  4. 否则,如果i是1,那么dp[i][j]等于j-1,因为使用的唯一操作是将1与本身相加。
  5. 如果j是1,那么dp[i][j]等于i-1,因为唯一的操作是从本身减去1。
  6. 否则,如果i和j不相等,需要考虑可以执行的三种操作:插入,删除或替换。这时候,我们需要计算执行每种操作所需的步骤。
  7. 计算插入操作所需的步骤,将目标值减少1,这个时候你需要将不断组合1直到等于i,如果组合后比j小,那么需要执行的步骤将等于1加上 dp[i][j-1]。
  8. 计算删除操作所需的步骤,将i减少1。然后,检查dp[i][j]和dp[i-1][j],选取最小值并将其加1,因为它表示将i转换为j所需的最少步数(即1+min(dp[i][j], dp[i-1][j]))。
  9. 计算替换操作所需的步骤,将i减少1,将j减少1,并检查dp[i][j],dp[i-1][j],dp[i][j-1]。选取最小值并将其加1,因为它表示将i转换为j所需的最少步数(即1+min(dp[i][j], dp[i-1][j], dp[i][j-1]))。
  10. 最后,dp[M][N]将是将M转换为N所需的最少步骤。

代码实现如下:

def convertNtoM(n, m):
    dp = [[0]*(n+1) for i in range(m+1)]
    
    for i in range(1, m+1):
        for j in range(1, n+1):
            if i == j:
                dp[i][j] = 0
            elif i == 1:
                dp[i][j] = j-1
            elif j == 1:
                dp[i][j] = i-1
            else:
                dp[i][j] = 1+min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1])
    
    return dp[m][n]

print(convertNtoM(15, 45)) # 3

这段代码将15转换为45的最少步骤是3。