通过重复添加除 1 以外的除数使 M 和 N 相等的最小移动 | Set-2(动态编程)
给定两个整数N和M ,任务是计算将N变为M的最小移动次数,其中在一次移动中,除了 1 之外,允许将N的当前值的任何除数添加到N本身。打印“-1 “如果不可能的话。
示例:
Input: N = 4, M = 24
Output: 5
Explanation: The given value of N can be converted into M using the following steps: (4)+2 -> (6)+2 -> (8)+4 -> (12)+6 -> (18)+6 -> 24. Hence, the count of moves is 5 which is the minimum possible.
Input: N = 4, M = 576
Output: 14
BFS 方法:给定问题已经在本文的 Set 1 中讨论过,它使用广度优先遍历来解决给定问题。
方法:本文重点介绍基于动态编程的不同方法。以下是要遵循的步骤:
- 创建一个一维数组dp[] ,其中dp[i]存储从N到达i的最小操作数。最初, dp[N+1… M] = {INT_MAX}和dp[N] = 0 。
- 使用变量i遍历范围[N, M] ,对于每个i ,遍历给定数字i的所有因子。对于因子X ,DP 关系可以定义如下:
dp[i + X] = min( dp[i], dp[i + X])
- 存储在dp[M]的值是所需的答案。
下面是上述方法的实现:
C++
// C++ implementation for the above approach
#include
using namespace std;
// Function to find the minimum count of
// operations to convert N to M
int minOperationCnt(int N, int M)
{
// Stores the DP state of the array
int dp[M + 1];
// Initialize each index with INT_MAX
for (int i = N + 1; i <= M; i++) {
dp[i] = INT_MAX;
}
// Initial condition
dp[N] = 0;
// Loop to iterate over range [N, M]
for (int i = N; i <= M; i++) {
// Check if this position
// can be reached or not
if (dp[i] == INT_MAX) {
continue;
}
// Loop to iterate through all divisors
// of the current value i
for (int j = 2; j * j <= i; j++) {
// If j is a divisor of i
if (i % j == 0) {
if (i + j <= M) {
// Update the value of dp[i + j]
dp[i + j] = min(dp[i + j], dp[i] + 1);
}
// Check for value i / j;
if (i + i / j <= M) {
// Update the value of dp[i + i/j]
dp[i + i / j]
= min(dp[i + i / j], dp[i] + 1);
}
}
}
}
// Return Answer
return (dp[M] == INT_MAX) ? -1 : dp[M];
}
// Driver Code
int main()
{
int N = 4;
int M = 576;
cout << minOperationCnt(N, M);
return 0;
}
Java
// Java implementation for the above approach
class GFG {
// Function to find the minimum count of
// operations to convert N to M
public static int minOperationCnt(int N, int M) {
// Stores the DP state of the array
int[] dp = new int[M + 1];
// Initialize each index with INT_MAX
for (int i = N + 1; i <= M; i++) {
dp[i] = Integer.MAX_VALUE;
}
// Initial condition
dp[N] = 0;
// Loop to iterate over range [N, M]
for (int i = N; i <= M; i++) {
// Check if this position
// can be reached or not
if (dp[i] == Integer.MAX_VALUE) {
continue;
}
// Loop to iterate through all divisors
// of the current value i
for (int j = 2; j * j <= i; j++) {
// If j is a divisor of i
if (i % j == 0) {
if (i + j <= M) {
// Update the value of dp[i + j]
dp[i + j] = Math.min(dp[i + j], dp[i] + 1);
}
// Check for value i / j;
if (i + i / j <= M) {
// Update the value of dp[i + i/j]
dp[i + i / j] = Math.min(dp[i + i / j], dp[i] + 1);
}
}
}
}
// Return Answer
return (dp[M] == Integer.MAX_VALUE) ? -1 : dp[M];
}
// Driver Code
public static void main(String args[]) {
int N = 4;
int M = 576;
System.out.println(minOperationCnt(N, M));
}
}
// This code is contributed by saurabh_jaiswal.
Python3
# python implementation for the above approach
import math
INT_MAX = 2147483647
# Function to find the minimum count of
# operations to convert N to M
def minOperationCnt(N, M):
# Stores the DP state of the array
dp = [0 for _ in range(M + 1)]
# Initialize each index with INT_MAX
for i in range(N+1, M+1):
dp[i] = INT_MAX
# Initial condition
dp[N] = 0
# Loop to iterate over range [N, M]
for i in range(N, M+1):
# Check if this position
# can be reached or not
if (dp[i] == INT_MAX):
continue
# Loop to iterate through all divisors
# of the current value i
for j in range(2, int(math.sqrt(i))+1):
# If j is a divisor of i
if (i % j == 0):
if (i + j <= M):
# Update the value of dp[i + j]
dp[i + j] = min(dp[i + j], dp[i] + 1)
# Check for value i / j;
if (i + i // j <= M):
# Update the value of dp[i + i/j]
dp[i + i // j] = min(dp[i + i // j], dp[i] + 1)
# Return Answer
if dp[M] == INT_MAX:
return -1
else:
return dp[M]
# Driver Code
if __name__ == "__main__":
N = 4
M = 576
print(minOperationCnt(N, M))
# This code is contributed by rakeshsahni
C#
// C# implementation for the above approach
using System;
class GFG
{
// Function to find the minimum count of
// operations to convert N to M
public static int minOperationCnt(int N, int M)
{
// Stores the DP state of the array
int[] dp = new int[M + 1];
// Initialize each index with INT_MAX
for (int i = N + 1; i <= M; i++)
{
dp[i] = int.MaxValue;
}
// Initial condition
dp[N] = 0;
// Loop to iterate over range [N, M]
for (int i = N; i <= M; i++)
{
// Check if this position
// can be reached or not
if (dp[i] == int.MaxValue)
{
continue;
}
// Loop to iterate through all divisors
// of the current value i
for (int j = 2; j * j <= i; j++)
{
// If j is a divisor of i
if (i % j == 0)
{
if (i + j <= M)
{
// Update the value of dp[i + j]
dp[i + j] = Math.Min(dp[i + j], dp[i] + 1);
}
// Check for value i / j;
if (i + i / j <= M)
{
// Update the value of dp[i + i/j]
dp[i + i / j] = Math.Min(dp[i + i / j], dp[i] + 1);
}
}
}
}
// Return Answer
return (dp[M] == int.MaxValue) ? -1 : dp[M];
}
// Driver Code
public static void Main()
{
int N = 4;
int M = 576;
Console.Write(minOperationCnt(N, M));
}
}
// This code is contributed by saurabh_jaiswal.
Javascript
输出
14
时间复杂度: O((M – N)*√(M – N))
辅助空间: O(M)