📌  相关文章
📜  使用给定的操作最小化移动以将 N 减少到 0

📅  最后修改于: 2022-05-13 01:56:09.322000             🧑  作者: Mango

使用给定的操作最小化移动以将 N 减少到 0

给定一个数字N,以及可以执行的一些操作,任务是找到将N转换为 0 的最小移动次数。在一次移动操作中,可以执行以下操作之一:

  • 将 N 的值递增或递减 1。
  • 将 N 的值乘以 -1。
  • 如果 N 是偶数,则将 N 的值除以 2。
  • 如果 N 是一个完美的正方形,则将 N 的值减小到 √N。

例子:

方法:给定的问题可以通过使用动态规划有效地解决。这个想法是在 0 上使用散列和广度优先搜索,直到达到N。使用散列,以便相同的数字不会被访问两次。可以按照以下步骤解决问题:

  • 通过将所有可以从 0 到达的可能数字添加到队列和哈希图中来使用 BFS,这样它们就不会被再次访问
  • 返回达到N后计算的移动次数。

下面是上述方法的实现:

C++
// C++ code for the above approach
#include 
using namespace std;
 
    class Node {
     public:
        int val, moves;
 
        // Constructor
        Node(int v, int m)
        {
 
            val = v;
            moves = m;
        }
    };
 
    // Function to calculate
    // minimum number of moves
    // required to convert N to 0
    int minMoves(int N)
    {
 
        // Initialize a hashset
        // to mark the visited numbers
        set set;
 
        // Initialize a queue
        queue q ;
 
        // Mark 0 as visited
        set.insert(0);
 
        // Add 0 into the queue
        q.push(new Node(0, 0));
 
        // while N is not reached
        while (!q.empty()) {
 
            // poll out current node
            Node *curr = q.front();
            q.pop();
 
            // If N is reached
            if (curr->val == N) {
 
                // Return the number of moves used
                return curr->moves;
            }
 
            if (set.find(curr->val - 1)==set.end()) {
 
                // Mark the number as visited
                set.insert(curr->val - 1);
 
                // Add the number in the queue
                q.push(new Node(curr->val - 1,
                               curr->moves + 1));
            }
            if (set.find(curr->val + 1)==set.end()) {
 
                // Mark the number as visited
                set.insert(curr->val + 1);
 
                // Add the number in the queue
                q.push(new Node(curr->val + 1,
                               curr->moves + 1));
            }
            if (set.find(curr->val * 2)==set.end()) {
 
                // Mark the number as visited
                set.insert(curr->val * 2);
 
                // Add the number in the queue
                q.push(new Node(curr->val * 2,
                               curr->moves + 1));
            }
            int sqr = curr->val * curr->val;
            if (set.find(sqr)==set.end()) {
 
                // Mark the number as visited
                set.insert(sqr);
 
                // Add the number in the queue
                q.push(new Node(sqr,
                               curr->moves + 1));
            }
            if (set.find(-curr->val)==set.end()) {
 
                // Mark the number as visited
                set.insert(-curr->val);
 
                // Add the number in the queue
                q.push(new Node(-curr->val,
                               curr->moves + 1));
            }
        }
 
        return -1;
    }
 
    // Driver code
     int main()
    {
 
        int N = 50;
 
        // Call the function
        // and print the answer
        cout<<(minMoves(N));
    }
 
// This code is contributed by Potta Lokesh


Java
// Java implementation for the above approach
 
import java.io.*;
import java.util.*;
 
class GFG {
 
    static class Node {
 
        int val, moves;
 
        // Constructor
        public Node(int val, int moves)
        {
 
            this.val = val;
            this.moves = moves;
        }
    }
 
    // Function to calculate
    // minimum number of moves
    // required to convert N to 0
    public static int minMoves(int N)
    {
 
        // Initialize a hashset
        // to mark the visited numbers
        Set set = new HashSet<>();
 
        // Initialize a queue
        Queue q = new LinkedList<>();
 
        // Mark 0 as visited
        set.add(0);
 
        // Add 0 into the queue
        q.add(new Node(0, 0));
 
        // while N is not reached
        while (!q.isEmpty()) {
 
            // poll out current node
            Node curr = q.poll();
 
            // If N is reached
            if (curr.val == N) {
 
                // Return the number of moves used
                return curr.moves;
            }
 
            if (!set.contains(curr.val - 1)) {
 
                // Mark the number as visited
                set.add(curr.val - 1);
 
                // Add the number in the queue
                q.add(new Node(curr.val - 1,
                               curr.moves + 1));
            }
            if (!set.contains(curr.val + 1)) {
 
                // Mark the number as visited
                set.add(curr.val + 1);
 
                // Add the number in the queue
                q.add(new Node(curr.val + 1,
                               curr.moves + 1));
            }
            if (!set.contains(curr.val * 2)) {
 
                // Mark the number as visited
                set.add(curr.val * 2);
 
                // Add the number in the queue
                q.add(new Node(curr.val * 2,
                               curr.moves + 1));
            }
            int sqr = curr.val * curr.val;
            if (!set.contains(sqr)) {
 
                // Mark the number as visited
                set.add(sqr);
 
                // Add the number in the queue
                q.add(new Node(sqr,
                               curr.moves + 1));
            }
            if (!set.contains(-curr.val)) {
 
                // Mark the number as visited
                set.add(-curr.val);
 
                // Add the number in the queue
                q.add(new Node(-curr.val,
                               curr.moves + 1));
            }
        }
 
        return -1;
    }
 
    // Driver code
    public static void main(String[] args)
    {
 
        int N = 50;
 
        // Call the function
        // and print the answer
        System.out.println(minMoves(N));
    }
}


Python3
# Python code for the above approach
from queue import Queue
 
class Node:
 
    # Constructor
    def __init__(self, v, m):
        self.val = v
        self.moves = m
 
# Function to calculate
# minimum number of moves
# required to convert N to 0
def minMoves(N):
 
    # Initialize a hashset
    # to mark the visited numbers
    _set = set()
 
    # Initialize a queue
    q = Queue()
 
    # Mark 0 as visited
    _set.add(0)
 
    # Add 0 into the queue
    q.put(Node(0, 0))
 
    # while N is not reached
    while (q.qsize):
 
        # poll out current node
        curr = q.queue[0]
        q.get()
 
        # If N is reached
        if (curr.val == N):
 
            # Return the number of moves used
            return curr.moves
 
        if (not (curr.val - 1) in _set):
 
            # Mark the number as visited
            _set.add(curr.val - 1)
 
            # Add the number in the queue
            q.put(Node(curr.val - 1, curr.moves + 1))
 
        if (not (curr.val + 1) in _set):
 
            # Mark the number as visited
            _set.add(curr.val + 1)
 
            # Add the number in the queue
            q.put(Node(curr.val + 1, curr.moves + 1))
 
        if (not (curr.val * 2) in _set):
 
            # Mark the number as visited
            _set.add(curr.val * 2)
 
            # Add the number in the queue
            q.put(Node(curr.val * 2, curr.moves + 1))
 
        sqr = curr.val * curr.val
        if (not sqr in _set):
 
            # Mark the number as visited
            _set.add(sqr)
 
            # Add the number in the queue
            q.put(Node(sqr, curr.moves + 1))
 
        if (not (-curr.val) in _set):
 
            # Mark the number as visited
            _set.add(-curr.val)
 
            # Add the number in the queue
            q.put(Node(-curr.val, curr.moves + 1))
 
    return -1
 
# Driver code
N = 50
 
# Call the function
# and print the answer
print((minMoves(N)))
 
# This code is contributed by gfgking


Javascript


输出
6

时间复杂度: O(log N)
辅助空间: O(K*log N),其中 K 是允许的可能操作