Minimum cost to reduce A and B to 0 using square root or divide by 2
Last Updated :
07 Jul, 2023
Given two integers A and B, the task is to convert the given two integers to zero at minimal cost by performing the following two types of operations:
- Replace both integers A and B by the square root of the product of A and B. This operation will cost 2 units.
- Replace A by A/2 or B by B/2 respectively. This operation will cost 1 unit.
Example:
Input: A = 2, B = 2
Output: 4
Explanation:
Operation 1: Apply first operation on A, making A=1, B=2. Cost=1
Operation 2: Apply first operation again on A, making A=0, B=2. Cost=2
Operation 3: Apply second operation on both A and B, making A=0, B=0. Cost=4.
Input: A = 53, B = 16
Output: 7
Approach:
This problem can be solved by exploring all possibilities using a recursive tree and then memoizing the solution in a matrix. To solve this problem follow the below steps:
- Create a function getMinOperations with five parameters that are A, B, prevA, prevB, and a dp matrix, here prevA and prevB are the previous value of A and B. This function will return the minimum cost required to make A and B to zero.
- Now, call this function initially with arguments, A, B, prevA = -1, prevB = -1 and dp.
- In each call:
- First, check if the value of A and B is equal to the value of prevA and prevB. If they are, return INT_MAX from this call as this call is resulting in no change in the values of A and B and therefore will resulting in an infinite recursive loop.
- Check for the base case that is both A and B are zero. If they are, return 0 from this call because the minimum cost to convert A and B to zero is 0 at this stage.
- Also, check if this recursive call is already memorized in the dp matrix. If it is, then return the value from the matrix.
- Now, the answer of every recursive call is the minimum of the answers provided by three subproblems:
- Minimum cost if A is reduced to A/2.
- Minimum cost if B is reduced to B/2.
- Minimum cost if both A and B is reduced to sqrt(A*B).
- Find the minimum of these three values and memoize it while returning from the current recursive call.
- The function will return the minimum cost after all recursive calls are made.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int getMinOperations( int A, int B,
int prevA, int prevB,
vector<vector< int > >& dp)
{
if (A == prevA and B == prevB) {
return INT_MAX;
}
if (A == 0 and B == 0) {
return 0;
}
if (dp[A][B] != -1) {
return dp[A][B];
}
int ans1 = getMinOperations(
A / 2, B, A, B, dp);
if (ans1 != INT_MAX) {
ans1 += 1;
}
int ans2 = getMinOperations(
A, B / 2, A, B, dp);
if (ans2 != INT_MAX) {
ans2 += 1;
}
int ans3 = getMinOperations( sqrt (A * B),
sqrt (A * B), A,
B, dp);
if (ans3 != INT_MAX) {
ans3 += 2;
}
return dp[A][B] = min({ ans1, ans2, ans3 });
}
int main()
{
int A = 53, B = 16;
int mx = max(A, B);
vector<vector< int > > dp(
mx + 1,
vector< int >(mx + 1, -1));
cout << getMinOperations(
A, B, -1, -1, dp);
}
|
Java
import java.io.*;
class GFG
{
static int getMinOperations( int A, int B, int prevA,
int prevB, int dp[][])
{
if (A == prevA && B == prevB) {
return Integer.MAX_VALUE;
}
if (A == 0 && B == 0 ) {
return 0 ;
}
if (dp[A][B] != - 1 ) {
return dp[A][B];
}
int ans1 = getMinOperations(A / 2 , B, A, B, dp);
if (ans1 != Integer.MAX_VALUE) {
ans1 += 1 ;
}
int ans2 = getMinOperations(A, B / 2 , A, B, dp);
if (ans2 != Integer.MAX_VALUE) {
ans2 += 1 ;
}
int ans3 = getMinOperations(( int )Math.sqrt(A * B),
( int )Math.sqrt(A * B),
A, B, dp);
if (ans3 != Integer.MAX_VALUE) {
ans3 += 2 ;
}
return dp[A][B]
= Math.min(ans1, Math.min(ans2, ans3));
}
public static void main(String[] args)
{
int A = 53 , B = 16 ;
int mx = Math.max(A, B);
int dp[][] = new int [mx + 1 ][mx + 1 ];
for ( int i = 0 ; i <= mx; i++) {
for ( int j = 0 ; j <= mx; j++)
dp[i][j] = - 1 ;
}
System.out.println(
getMinOperations(A, B, - 1 , - 1 , dp));
}
}
|
Python3
import math as Math
def getMinOperations(A, B, prevA, prevB, dp):
if (A = = prevA and B = = prevB):
return 10 * * 9 ;
if (A = = 0 and B = = 0 ):
return 0 ;
if (dp[A][B] ! = - 1 ):
return dp[A][B];
ans1 = getMinOperations(A / / 2 , B, A, B, dp);
if (ans1 ! = 10 * * 9 ):
ans1 + = 1 ;
ans2 = getMinOperations(A, B / / 2 , A, B, dp);
if (ans2 ! = 10 * * 9 ):
ans2 + = 1 ;
ans3 = getMinOperations(
Math.floor(Math.sqrt(A * B)),
Math.floor(Math.sqrt(A * B)),
A,
B,
dp
);
if (ans3 ! = 10 * * 9 ):
ans3 + = 2 ;
dp[A][B] = min (ans1, min (ans2, ans3))
return dp[A][B];
A = 53
B = 16
mx = max (A, B);
dp = [[ - 1 for i in range (mx + 1 )] for i in range (mx + 1 )]
print (getMinOperations(A, B, - 1 , - 1 , dp));
|
C#
using System;
using System.Collections;
class GFG
{
static int getMinOperations( int A, int B, int prevA,
int prevB, int [,]dp)
{
if (A == prevA && B == prevB) {
return Int32.MaxValue;
}
if (A == 0 && B == 0) {
return 0;
}
if (dp[A, B] != -1) {
return dp[A, B];
}
int ans1 = getMinOperations(A / 2, B, A, B, dp);
if (ans1 != Int32.MaxValue) {
ans1 += 1;
}
int ans2 = getMinOperations(A, B / 2, A, B, dp);
if (ans2 != Int32.MaxValue) {
ans2 += 1;
}
int ans3 = getMinOperations(( int )Math.Sqrt(A * B),
( int )Math.Sqrt(A * B),
A, B, dp);
if (ans3 != Int32.MaxValue) {
ans3 += 2;
}
return dp[A, B]
= Math.Min(ans1, Math.Min(ans2, ans3));
}
public static void Main()
{
int A = 53, B = 16;
int mx = Math.Max(A, B);
int [,]dp = new int [mx + 1, mx + 1];
for ( int i = 0; i <= mx; i++) {
for ( int j = 0; j <= mx; j++)
dp[i, j] = -1;
}
Console.Write(
getMinOperations(A, B, -1, -1, dp));
}
}
|
Javascript
<script>
function getMinOperations(A, B, prevA, prevB, dp) {
if (A == prevA && B == prevB) {
return Number.MAX_SAFE_INTEGER;
}
if (A == 0 && B == 0) {
return 0;
}
if (dp[A][B] != -1) {
return dp[A][B];
}
let ans1 = getMinOperations(Math.floor(A / 2), B, A, B, dp);
if (ans1 != Number.MAX_SAFE_INTEGER) {
ans1 += 1;
}
let ans2 = getMinOperations(A, Math.floor(B / 2), A, B, dp);
if (ans2 != Number.MAX_SAFE_INTEGER) {
ans2 += 1;
}
let ans3 = getMinOperations(
Math.floor(Math.sqrt(A * B)),
Math.floor(Math.sqrt(A * B)),
A,
B,
dp
);
if (ans3 != Number.MAX_SAFE_INTEGER) {
ans3 += 2;
}
return (dp[A][B] = Math.min(ans1, Math.min(ans2, ans3)));
}
let A = 53,
B = 16;
let mx = Math.max(A, B);
let dp = new Array(mx + 1).fill(0).map(() => new Array(mx + 1).fill(-1));
document.write(getMinOperations(A, B, -1, -1, dp));
</script>
|
Time Complexity: O(max(A, B)^2)
Auxiliary Space: O(max(A, B)^2)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a 2D DP to store the solution of the subproblems and initialize it with 0.
- Initialize the DP with base cases
- Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
- Create three variables ans1, ans2, and ans3 to keep track of answers in 3 different conditions.
- update the current value of DP minimum of ans1, ans2 and ans3.
- At last return final answer stored in dp[A][B].
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int getMinOperations( int A, int B) {
int mx = max(A, B);
vector<vector< int >> dp(mx + 1, vector< int >(mx + 1, 0));
for ( int i = 1; i <= A; i++) {
for ( int j = 1; j <= B; j++) {
if (i == 1 && j == 1) {
dp[i][j] = 0;
} else {
int ans1 = INT_MAX, ans2 = INT_MAX, ans3 = INT_MAX;
if (i >= 2) {
ans1 = dp[i/2][j];
if (ans1 != INT_MAX) {
ans1 += 1;
}
}
if (j >= 2) {
ans2 = dp[i][j/2];
if (ans2 != INT_MAX) {
ans2 += 1;
}
}
int s = sqrt (i*j);
if (s*s == i*j) {
ans3 = dp[s][s];
if (ans3 != INT_MAX) {
ans3 += 2;
}
}
dp[i][j] = min({ ans1, ans2, ans3 });
}
}
}
return dp[A][B];
}
int main() {
int A = 53, B = 16;
cout << getMinOperations(A, B);
return 0;
}
|
Java
import java.util.*;
public class Main
{
static int getMinOperations( int A, int B) {
int mx = Math.max(A, B);
int [][] dp = new int [mx + 1 ][mx + 1 ];
for ( int i = 1 ; i <= mx; i++) {
Arrays.fill(dp[i], 0 );
}
for ( int i = 1 ; i <= A; i++) {
for ( int j = 1 ; j <= B; j++) {
if (i == 1 && j == 1 ) {
dp[i][j] = 0 ;
} else {
int ans1 = Integer.MAX_VALUE, ans2 = Integer.MAX_VALUE, ans3 = Integer.MAX_VALUE;
if (i >= 2 ) {
ans1 = dp[i/ 2 ][j];
if (ans1 != Integer.MAX_VALUE) {
ans1 += 1 ;
}
}
if (j >= 2 ) {
ans2 = dp[i][j/ 2 ];
if (ans2 != Integer.MAX_VALUE) {
ans2 += 1 ;
}
}
int s = ( int )Math.sqrt(i*j);
if (s*s == i*j) {
ans3 = dp[s][s];
if (ans3 != Integer.MAX_VALUE) {
ans3 += 2 ;
}
}
dp[i][j] = Math.min(Math.min(ans1, ans2), ans3);
}
}
}
return dp[A][B];
}
public static void main(String[] args) {
int A = 53 , B = 16 ;
System.out.println(getMinOperations(A, B));
}
}
|
Python3
import math
def getMinOperations(A, B):
mx = max (A, B)
dp = [[ 0 for j in range (mx + 1 )] for i in range (mx + 1 )]
for i in range ( 1 , A + 1 ):
for j in range ( 1 , B + 1 ):
if (i = = 1 and j = = 1 ):
dp[i][j] = 0
else :
ans1, ans2, ans3 = math.inf, math.inf, math.inf
if (i > = 2 ):
ans1 = dp[i / / 2 ][j]
if (ans1 ! = math.inf):
ans1 + = 1
if (j > = 2 ):
ans2 = dp[i][j / / 2 ]
if (ans2 ! = math.inf):
ans2 + = 1
s = int (math.sqrt(i * j))
if (s * s = = i * j):
ans3 = dp[s][s]
if (ans3 ! = math.inf):
ans3 + = 2
dp[i][j] = min (ans1, ans2, ans3)
return dp[A][B]
if __name__ = = '__main__' :
A = 53
B = 16
print (getMinOperations(A, B))
|
C#
using System;
public class GFG {
static int getMinOperations( int A, int B)
{
int mx = Math.Max(A, B);
int [, ] dp = new int [mx + 1, mx + 1];
for ( int i = 1; i <= A; i++) {
for ( int j = 1; j <= B; j++) {
if (i == 1 && j == 1) {
dp[i, j] = 0;
}
else {
int ans1 = int .MaxValue,
ans2 = int .MaxValue,
ans3 = int .MaxValue;
if (i >= 2) {
ans1 = dp[i / 2, j];
if (ans1 != int .MaxValue) {
ans1 += 1;
}
}
if (j >= 2) {
ans2 = dp[i, j / 2];
if (ans2 != int .MaxValue) {
ans2 += 1;
}
}
int s = ( int )Math.Sqrt(i * j);
if (s * s == i * j) {
ans3 = dp[s, s];
if (ans3 != int .MaxValue) {
ans3 += 2;
}
}
dp[i, j] = Math.Min(
ans1, Math.Min(ans2, ans3));
}
}
}
return dp[A, B];
}
public static void Main()
{
int A = 53;
int B = 16;
Console.WriteLine(getMinOperations(A, B));
}
}
|
Javascript
function getMinOperations(A, B) {
let mx = Math.max(A, B);
let dp = new Array(mx + 1);
for (let i = 0; i <= mx; i++) {
dp[i] = new Array(mx + 1).fill(0);
}
for (let i = 1; i <= A; i++) {
for (let j = 1; j <= B; j++) {
if (i === 1 && j === 1) {
dp[i][j] = 0;
}
else {
let ans1 = Infinity, ans2 = Infinity, ans3 = Infinity;
if (i >= 2) {
ans1 = dp[Math.floor(i / 2)][j];
if (ans1 !== Infinity) {
ans1 += 1;
}
}
if (j >= 2) {
ans2 = dp[i][Math.floor(j / 2)];
if (ans2 !== Infinity) {
ans2 += 1;
}
}
let s = Math.floor(Math.sqrt(i * j));
if (s * s === i * j) {
ans3 = dp[s][s];
if (ans3 !== Infinity) {
ans3 += 2;
}
}
dp[i][j] = Math.min(ans1, ans2, ans3);
}
}
}
return dp[A][B];
}
let A = 53, B = 16;
console.log(getMinOperations(A, B));
|
Output
7
Time Complexity: O(max(A, B)^2)
Auxiliary Space: O(max(A, B)^2)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...