Open In App

Camel and Banana Puzzle | DP

A person wants to transfer bananas over to a destination A km away. He initially has B bananas and a camel. The camel cannot carry more than C bananas at a time and eats a banana every km it travels. Given three integers A, B, and C, the task is to find the maximum number of bananas the person can transfer to the destination using the camel.

Note: The given problem is a generalized version of the famous Camel-Banana puzzle.



Examples:

Input: A = 10, B = 30, C = 10 
Output: 5



Input: A = 1000, B = 3000, C = 1000
Output: 533

Approach: The given problem can be solved with the help of Dynamic Programming using Memoization using the following key points:

 Using the above observations, the given problem can be solved by following the below steps:

Below is the implementation of the above approach:




// C++ program of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Stores the overlapping state
int dp[1001][3001];
 
// Recursive function to find the maximum
// number of bananas that can be transferred
// to A distance using memoization
int recBananaCnt(int A, int B, int C)
{
    // Base Case where count of bananas
    // is less that the given distance
    if (B <= A) {
        return 0;
    }
 
    // Base Case where count of bananas
    // is less that camel's capacity
    if (B <= C) {
        return B - A;
    }
 
    // Base Case where distance = 0
    if (A == 0) {
        return B;
    }
 
    // If the current state is already
    // calculated
    if (dp[A][B] != -1) {
        return dp[A][B];
    }
 
    // Stores the maximum count of bananas
    int maxCount = INT_MIN;
 
    // Stores the number of trips to transfer
    // B bananas using a camel of capacity C
    int tripCount = B % C == 0 ? ((2 * B) / C) - 1
                               : ((2 * B) / C) + 1;
 
    // Loop to iterate over all the
    // breakpoints in range [1, A]
    for (int i = 1; i <= A; i++) {
 
        // Recursive call over the
        // remaining path
        int curCount
            = recBananaCnt(A - i,
                           B - tripCount * i, C);
 
        // Update the maxCount
        if (curCount > maxCount) {
            maxCount = curCount;
 
            // Memoize the current value
            dp[A][B] = maxCount;
        }
    }
 
    // Return answer
    return maxCount;
}
 
// Function to find the maximum number of
// bananas that can be transferred
int maxBananaCnt(int A, int B, int C)
{
    // Initialize dp array with -1
    memset(dp, -1, sizeof(dp));
 
    // Function Call
    return recBananaCnt(A, B, C);
}
 
// Driver Code
int main()
{
    int A = 1000;
    int B = 3000;
    int C = 1000;
    cout << maxBananaCnt(A, B, C);
 
    return 0;
}




// Java program of the above approach
public class GFG {
     
    // Stores the overlapping state
    final static int dp[][] = new int[1001][3001];
 
    // Recursive function to find the maximum
    // number of bananas that can be transferred
    // to A distance using memoization
    static int recBananaCnt(int A, int B, int C)
    {
    
                 
        // Base Case where count of bananas
        // is less that the given distance
        if (B <= A) {
            return 0;
        }
     
        // Base Case where count of bananas
        // is less that camel's capacity
        if (B <= C) {
            return B - A;
        }
     
        // Base Case where distance = 0
        if (A == 0) {
            return B;
        }
     
        // If the current state is already
        // calculated
        if (dp[A][B] != -1) {
            return dp[A][B];
        }
     
        // Stores the maximum count of bananas
        int maxCount = Integer.MIN_VALUE;
     
        // Stores the number of trips to transfer
        // B bananas using a camel of capacity C
        int tripCount = B % C == 0 ? ((2 * B) / C) - 1 : ((2 * B) / C) + 1;
     
        // Loop to iterate over all the
        // breakpoints in range [1, A]
        for (int i = 1; i <= A; i++) {
     
            // Recursive call over the
            // remaining path
            int curCount
                = recBananaCnt(A - i,
                               B - tripCount * i, C);
     
            // Update the maxCount
            if (curCount > maxCount) {
                maxCount = curCount;
     
                // Memoize the current value
                dp[A][B] = maxCount;
            }
        }
     
        // Return answer
        return maxCount;
    }
     
    // Function to find the maximum number of
    // bananas that can be transferred
    static int maxBananaCnt(int A, int B, int C)
    {
        // Initialize dp array with -1
        for(int i = 0; i < 1001; i++)
            for (int j = 0; j < 3001; j++)
                dp[i][j] = -1;
     
        // Function Call
        return recBananaCnt(A, B, C);
    }
 
    // Driver Code
    public static void main (String[] args) {
         
            int A = 1000;
            int B = 3000;
            int C = 1000;
            System.out.println(maxBananaCnt(A, B, C));
    }
}
 
// This code is contributed by AnkThon




# Python program of the above approach
# Stores the overlapping state
dp = [[-1 for i in range(3001)] for j in range(1001)]
 
# Recursive function to find the maximum
# number of bananas that can be transferred
# to A distance using memoization
def recBananaCnt(A, B, C):
 
    # Base Case where count of bananas
    # is less that the given distance
    if (B <= A):
        return 0
         
    # Base Case where count of bananas
    # is less that camel's capacity
    if (B <= C):
        return B - A
     
    # Base Case where distance = 0
    if (A == 0):
        return B
     
 
    # If the current state is already
    # calculated
    if (dp[A][B] != -1):
        return dp[A][B]
     
 
    # Stores the maximum count of bananas
    maxCount = -2**32
 
    # Stores the number of trips to transfer
    # B bananas using a camel of capacity C
    tripCount = ((2 * B) // C) - 1 if(B % C == 0 ) else ((2 * B) // C) + 1
 
    # Loop to iterate over all the
    # breakpoints in range [1, A]
    for i in range(1,A+1):
 
        # Recursive call over the
        # remaining path
        curCount = recBananaCnt(A - i, B - tripCount * i, C)
 
        # Update the maxCount
        if (curCount > maxCount):
            maxCount = curCount
 
            # Memoize the current value
            dp[A][B] = maxCount
         
    # Return answer
    return maxCount
 
# Function to find the maximum number of
# bananas that can be transferred
def maxBananaCnt(A, B, C):
 
    # Function Call
    return recBananaCnt(A, B, C)
 
# Driver Code
A = 1000
B = 3000
C = 1000
print(maxBananaCnt(A, B, C))
 
# This code is contributed by shivanisinghss2110




// C# program of the above approach
using System;
 
public class GFG {
 
    // Stores the overlapping state
    static int[, ] dp = new int[1001, 3001];
 
    // Recursive function to find the maximum
    // number of bananas that can be transferred
    // to A distance using memoization
    static int recBananaCnt(int A, int B, int C)
    {
 
        // Base Case where count of bananas
        // is less that the given distance
        if (B <= A) {
            return 0;
        }
 
        // Base Case where count of bananas
        // is less that camel's capacity
        if (B <= C) {
            return B - A;
        }
 
        // Base Case where distance = 0
        if (A == 0) {
            return B;
        }
 
        // If the current state is already
        // calculated
        if (dp[A, B] != -1) {
            return dp[A, B];
        }
 
        // Stores the maximum count of bananas
        int maxCount = Int32.MinValue;
 
        // Stores the number of trips to transfer
        // B bananas using a camel of capacity C
        int tripCount = B % C == 0 ? ((2 * B) / C) - 1
                                   : ((2 * B) / C) + 1;
 
        // Loop to iterate over all the
        // breakpoints in range [1, A]
        for (int i = 1; i <= A; i++) {
 
            // Recursive call over the
            // remaining path
            int curCount
                = recBananaCnt(A - i, B - tripCount * i, C);
 
            // Update the maxCount
            if (curCount > maxCount) {
                maxCount = curCount;
 
                // Memoize the current value
                dp[A, B] = maxCount;
            }
        }
 
        // Return answer
        return maxCount;
    }
 
    // Function to find the maximum number of
    // bananas that can be transferred
    static int maxBananaCnt(int A, int B, int C)
    {
       
        // Initialize dp array with -1
        for (int i = 0; i < 1001; i++)
            for (int j = 0; j < 3001; j++)
                dp[i, j] = -1;
 
        // Function Call
        return recBananaCnt(A, B, C);
    }
 
    // Driver Code
    public static void Main(string[] args)
    {
 
        int A = 1000;
        int B = 3000;
        int C = 1000;
        Console.WriteLine(maxBananaCnt(A, B, C));
    }
}
 
// This code is contributed by ukasp.




<script>
       // JavaScript Program to implement
       // the above approach
 
       // Stores the overlapping state
       // Initialize dp array with -1
       let dp = new Array(1001);
       for (let i = 0; i < dp.length; i++)
       {
           dp[i] = (new Array(3001).fill(-1))
       }
 
       // Recursive function to find the maximum
       // number of bananas that can be transferred
       // to A distance using memoization
       function recBananaCnt(A, B, C)
       {
        
           // Base Case where count of bananas
           // is less that the given distance
           if (B <= A) {
               return 0;
           }
 
           // Base Case where count of bananas
           // is less that camel's capacity
           if (B <= C) {
               return B - A;
           }
 
           // Base Case where distance = 0
           if (A == 0) {
               return B;
           }
 
           // If the current state is already
           // calculated
           if (dp[A][B] != -1) {
               return dp[A][B];
           }
 
           // Stores the maximum count of bananas
           let maxCount = Number.MIN_VALUE;
 
           // Stores the number of trips to transfer
           // B bananas using a camel of capacity C
           let tripCount = B % C == 0 ? Math.floor((2 * B) / C) - 1
               : Math.floor((2 * B) / C) + 1;
 
           // Loop to iterate over all the
           // breakpoints in range [1, A]
           for (let i = 1; i <= A; i++) {
 
               // Recursive call over the
               // remaining path
               let curCount
                   = recBananaCnt(A - i,
                       B - tripCount * i, C);
 
               // Update the maxCount
               if (curCount > maxCount) {
                   maxCount = curCount;
 
                   // Memoize the current value
                   dp[A][B] = maxCount;
               }
           }
 
           // Return answer
           return maxCount;
       }
 
       // Function to find the maximum number of
       // bananas that can be transferred
       function maxBananaCnt(A, B, C) {
           // Function Call
           return recBananaCnt(A, B, C);
       }
 
       // Driver Code
       let A = 1000;
       let B = 3000;
       let C = 1000;
       document.write(maxBananaCnt(A, B, C));
 
    // This code is contributed by Potta Lokesh
   </script>

Output: 
533

 

Time Complexity: O(A*A*B)
Auxiliary Space: O(A*B)

 


Article Tags :