Open In App

Minimum cost to convert a ‘1’ to a given number

Last Updated : 11 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a positive integer ‘n’. Starting with 1 find the minimum cost required to convert it to n using the following operations :

  • Multiply the number by 2 with costs a
  • Add 1 to the number with costs b
  • Subtract 1 from the number with costs c.

Examples:

Input: n = 31, a = 2, b = 5, c = 3
Output: 13
Explanation: The minimum cost transition to convert 1 to 31 is shown below:

  • 1 -> 2 -> 4 -> 8 -> 16 -> 32 -> 31.
  • Total cost = a+a+a+a+a+c = 2+2+2+2+2+3 = 13

Input: n = 31, a = 2, b = 1, c = 3
Output: 11
Explanation: The minimum cost transition to convert 1 to 31 is shown below:

  • 1 -> 2 -> 3 -> 6 -> 7 -> 14 -> 15 -> 30 -> 31.
  • Total cost = b+b+a+b+a+b+a+b = 1+1+2+1+2+1+2+1 = 11

Approach: To solve the problem follow the below idea:

The problem can be solved by exploring different paths to reach the target number while keeping track of the costs. This can be done using data structures such as priority queues. It starts with the number 1 and systematically applies three operations: Doubling the number, adding 1, and subtracting 1. These operations generate new numbers. The priority queue ensures that paths with lower costs are explored first, helping to find the minimum cost to reach the target number ‘n’. This approach is like searching the “cheapest” path through a number space to reach the desired value.

Let’s break down the approach and the code:

  • A priority queue (min-heap) named ‘pq’ is used to store pairs of integers {number, cost}. The comparator for the priority queue ensures that pairs with lower costs come first. The code initializes ans (the minimum cost) to 0 and creates a vector vis of size 2 * n to mark visited numbers. The priority queue is initialized with the starting number 1 and cost 0.
  • The loop continues until the priority queue is empty:
    • The top element f of the priority queue is popped.
    • If the popped number f.first is equal to the target number n, the minimum cost ans is updated to f.second, and the loop is exited.
    • If the number f.first has already been visited, the loop continues without processing it again.
    • If the number f.first * 2 is within the acceptable range and has not been visited, it’s pushed into the priority queue with an increased cost f.second + a.
    • If the number f.first + 1 is within the acceptable range and has not been visited, it’s pushed into the priority queue with an increased cost f.second + b.
    • If the number f.first – 1 is greater than 1 and has not been visited, it’s pushed into the priority queue with an increased cost f.second + c.
  • After the loop ends, the minimum cost required to reach the target number n is stored in the variable ans, which is then printed.
  • This approach is a variation of Dijkstra’s algorithm, where you explore possible number transitions with their associated costs. By using a priority queue, the algorithm always explores the path with the lowest cost first. This ensures that when the target number n is reached, the associated cost is indeed the minimum cost required to reach it.

Below is the implementation of the above approach:

C++




// C++ code to convert 1 to n in minimum cost
// possible using given operations
#include <bits/stdc++.h>
using namespace std;
class X {
public:
   
    // Comparator for the priority queue to make
    // sure pairs with lower costs come first.
    bool operator()(pair<int, int>& a, pair<int, int>& b)
    {
        return a.second > b.second;
    }
};
 
int min_cost(int n, int a, int b, int c)
{
    int ans;
    vector<int> vis(2 * n);
 
    priority_queue<pair<int, int>, vector<pair<int, int> >,
                   X>
        pq;
 
    pq.push({ 1, 0 });
 
    while (!pq.empty()) {
 
        // pop the top pair from pq
        auto f = pq.top();
 
        pq.pop();
        if (f.first == n) {
 
            // if the destination number is
            // reached break out of the loop
            ans = f.second;
            break;
        }
 
        // if already visited continue
        if (vis[f.first] == 1)
            continue;
 
        vis[f.first] = 1;
 
        if (2 * f.first < 2 * n && vis[f.first * 2] == 0) {
            pq.push({ f.first * 2, f.second + a });
        }
        if (f.first + 1 < 2 * n && vis[f.first + 1] == 0) {
            pq.push({ f.first + 1, f.second + b });
        }
        if (f.first - 1 > 1 && vis[f.first - 1] == 0) {
            pq.push({ f.first - 1, f.second + c });
        }
    }
 
    return ans;
}
 
// Drivers code
signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
 
    // Denotes number 'n'
    int n = 31;
 
    // Denotes cost 'a'
    int a = 2;
 
    // Denotes cost 'b'
    int b = 1;
 
    // Denotes cost 'c'
    int c = 3;
 
    // Function call
    cout << min_cost(n, a, b, c) << "\n";
 
    return 0;
}


Java




// Java code to convert 1 to n in minimum cost possible using given operations
import java.util.*;
 
class Pair {
    public int first, second;
 
    Pair(int first, int second)
    {
        this.first = first;
        this.second = second;
    }
}
 
class X implements Comparator<Pair> {
      // comparator for the priority queue to make sure pairs with lower costs come first.
    public int compare(Pair a, Pair b)
    {
        return a.second - b.second;
    }
}
 
public class GFG {
 
    static int minCost(int n, int a, int b, int c)
    {
        int ans = 0;
        boolean[] vis = new boolean[2 * n];
 
        PriorityQueue<Pair> pq
            = new PriorityQueue<>(new X());
        pq.add(new Pair(1, 0));
 
        while (!pq.isEmpty()) {
            Pair f = pq.poll();             // pop the top pair from pq
            if (f.first == n) {
                ans = f.second;             // if the destination number is reached break out of the loop
                break;
            }
            if (vis[f.first] == true)       // if already visited continue
                continue;
 
            vis[f.first] = true;
 
            if (2 * f.first < 2 * n
                && vis[2 * f.first] == false) {
                pq.add(new Pair(2 * f.first, f.second + a));
            }
            if (f.first + 1 < 2 * n
                && vis[f.first + 1] == false) {
                pq.add(new Pair(f.first + 1, f.second + b));
            }
            if (f.first - 1 > 1
                && vis[f.first - 1] == false) {
                pq.add(new Pair(f.first - 1, f.second + c));
            }
        }
 
        return ans;
    }
 
    public static void main(String[] args)
    {
        int n = 31;
        int a = 2;
        int b = 1;
        int c = 3;
 
        System.out.println(minCost(n, a, b, c));
    }
}
// This code is contribured by Shikhar Reyya


Python3




# python code to convert 1 to n in minimum cost possible using given operations
import heapq
 
def min_cost(n, a, b, c):
    ans = 0
    vis = [0] * (2 * n)
 
    pq = []
    heapq.heappush(pq, (0, 1))  # Inverted order for the cost and value
 
    while pq:
        cost, f = heapq.heappop(pq)
        if f == n:
            ans = cost
            break
        if vis[f] == 1:
            continue
         
        vis[f] = 1
 
        if 2 * f < 2 * n and vis[2 * f] == 0:
            heapq.heappush(pq, (cost + a, 2 * f))
        if f + 1 < 2 * n and vis[f + 1] == 0:
            heapq.heappush(pq, (cost + b, f + 1))
        if f - 1 > 1 and vis[f - 1] == 0:
            heapq.heappush(pq, (cost + c, f - 1))
 
    return ans
 
n = 31
a = 2
b = 1
c = 3
print(min_cost(n, a, b, c))
# This code is contribured by Shikhar Reyya


C#




// C# code to convert 1 to n in minimum cost possible using given operations
using System;
using System.Collections.Generic;
 
class X : IComparer<Pair> {
      // comparator for the priority queue to make sure pairs with lower costs come first.
    public int Compare(Pair a, Pair b) {
        return a.Second.CompareTo(b.Second);
    }
}
 
class Pair {
    public int First { get; set; }
    public int Second { get; set; }
 
    public Pair(int first, int second) {
        First = first;
        Second = second;
    }
}
 
class GFG {
    static int MinCost(int n, int a, int b, int c) {
        int ans = 0;
 
        bool[] vis = new bool[2 * n];
 
        PriorityQueue<Pair> pq = new PriorityQueue<Pair>(new X());
        pq.Enqueue(new Pair(1, 0));
 
        while (pq.Count > 0) {
            Pair f = pq.Dequeue();                // pop the top pair from pq
            if (f.First == n) {
                ans = f.Second;           // if the destination number is reached break out of the loop
                break;
            }
            if (vis[f.First] == true) continue;        // if already visited continue
 
            vis[f.First] = true;
 
            if (2 * f.First < 2 * n && vis[2 * f.First] == false) {
                pq.Enqueue(new Pair(2 * f.First, f.Second + a));
            }
            if (f.First + 1 < 2 * n && vis[f.First + 1] == false) {
                pq.Enqueue(new Pair(f.First + 1, f.Second + b));
            }
            if (f.First - 1 > 1 && vis[f.First - 1] == false) {
                pq.Enqueue(new Pair(f.First - 1, f.Second + c));
            }
        }
 
        return ans;
    }
 
    public static void Main(string[] args) {
        int n = 31;
        int a = 2;
        int b = 1;
        int c = 3;
 
        Console.WriteLine(MinCost(n, a, b, c));
    }
 
    public class PriorityQueue<T> {
        private List<T> data;
        private IComparer<T> comparer;
 
        public PriorityQueue(IComparer<T> comparer) {
            this.data = new List<T>();
            this.comparer = comparer;
        }
 
        public void Enqueue(T item) {
            data.Add(item);
            int ci = data.Count - 1;
            while (ci > 0) {
                int pi = (ci - 1) / 2;
                if (comparer.Compare(data[ci], data[pi]) >= 0)
                    break;
                T tmp = data[ci]; data[ci] = data[pi]; data[pi] = tmp;
                ci = pi;
            }
        }
 
        public T Dequeue() {
            int li = data.Count - 1;
            T frontItem = data[0];
            data[0] = data[li];
            data.RemoveAt(li);
 
            --li;
            int pi = 0;
            while (true) {
                int ci = pi * 2 + 1;
                if (ci > li) break;
                int rc = ci + 1;
                if (rc <= li && comparer.Compare(data[rc], data[ci]) < 0)
                    ci = rc;
                if (comparer.Compare(data[pi], data[ci]) <= 0) break;
                T tmp = data[pi]; data[pi] = data[ci]; data[ci] = tmp;
                pi = ci;
            }
            return frontItem;
        }
 
        public T Peek() {
            T frontItem = data[0];
            return frontItem;
        }
 
        public int Count => data.Count;
    }
}
// This code is contribured by Shikhar Reyya


Javascript




// Javascript code for the above approach:
 
class Pair {
    constructor(first, second) {
        this.first = first;
        this.second = second;
    }
}
 
class PriorityQueue {
    constructor() {
        this.queue = [];
    }
 
    // Comparator for the priority queue to make sure pairs with lower costs come first.
    add(pair) {
        this.queue.push(pair);
        this.queue.sort((a, b) => a.second - b.second);
    }
 
    poll() {
        if (this.isEmpty()) {
            return null;
        }
        return this.queue.shift();
    }
 
    isEmpty() {
        return this.queue.length === 0;
    }
}
 
function minCost(n, a, b, c) {
    let ans = 0;
    const vis = new Array(2 * n).fill(false);
 
    const pq = new PriorityQueue();
    pq.add(new Pair(1, 0));
 
    while (!pq.isEmpty()) {
        const f = pq.poll();
        if (f.first === n) {
            ans = f.second;
            break;
        }
        if (vis[f.first]) {
            continue;
        }
 
        vis[f.first] = true;
 
        if (2 * f.first < 2 * n && !vis[2 * f.first]) {
            pq.add(new Pair(2 * f.first, f.second + a));
        }
        if (f.first + 1 < 2 * n && !vis[f.first + 1]) {
            pq.add(new Pair(f.first + 1, f.second + b));
        }
        if (f.first - 1 > 1 && !vis[f.first - 1]) {
            pq.add(new Pair(f.first - 1, f.second + c));
        }
    }
 
    return ans;
}
 
const n = 31;
const a = 2;
const b = 1;
const c = 3;
 
console.log(minCost(n, a, b, c));


Output

11




Time Complexity: O(n * log(n))
Auxiliary Space: O(n)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads