Camel and Banana Puzzle | DP
Last Updated :
15 Jun, 2022
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:
- It can be observed that the most effective way to transfer bananas is to divide the path (u, v) having A km into some smaller parts. Suppose x is a breakpoint in the path (u, v). The optimal choice is to transfer all the bananas from u to x and then from x to v.
- There can be any number of breakpoints in the path (u, v) such that the count of breakpoints < A.
- The total number of trips the camel which can carry C bananas at a time has to make in order to transfer X bananas over any distance can be calculated by the formula 2 * X / C – 1, if C is a factor of X (i.e, X % C = 0) otherwise 2 * X / C +1.
Using the above observations, the given problem can be solved by following the below steps:
- Consider a 2D array dp[][], where a state dp[A][B] represents the maximum number of bananas a camel can transfer over a distance of A km having B bananas initially. Initialize the dp[][] array with -1.
- Create a recursive function to iterate over the given path of A km and create a breakpoint at each valid index and recursively call the function for the remaining path.
- Memoize the maximum number of bananas for each state and return the memoized value if the current state is already calculated.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[1001][3001];
int recBananaCnt( int A, int B, int C)
{
if (B <= A) {
return 0;
}
if (B <= C) {
return B - A;
}
if (A == 0) {
return B;
}
if (dp[A][B] != -1) {
return dp[A][B];
}
int maxCount = INT_MIN;
int tripCount = B % C == 0 ? ((2 * B) / C) - 1
: ((2 * B) / C) + 1;
for ( int i = 1; i <= A; i++) {
int curCount
= recBananaCnt(A - i,
B - tripCount * i, C);
if (curCount > maxCount) {
maxCount = curCount;
dp[A][B] = maxCount;
}
}
return maxCount;
}
int maxBananaCnt( int A, int B, int C)
{
memset (dp, -1, sizeof (dp));
return recBananaCnt(A, B, C);
}
int main()
{
int A = 1000;
int B = 3000;
int C = 1000;
cout << maxBananaCnt(A, B, C);
return 0;
}
|
Java
public class GFG {
final static int dp[][] = new int [ 1001 ][ 3001 ];
static int recBananaCnt( int A, int B, int C)
{
if (B <= A) {
return 0 ;
}
if (B <= C) {
return B - A;
}
if (A == 0 ) {
return B;
}
if (dp[A][B] != - 1 ) {
return dp[A][B];
}
int maxCount = Integer.MIN_VALUE;
int tripCount = B % C == 0 ? (( 2 * B) / C) - 1 : (( 2 * B) / C) + 1 ;
for ( int i = 1 ; i <= A; i++) {
int curCount
= recBananaCnt(A - i,
B - tripCount * i, C);
if (curCount > maxCount) {
maxCount = curCount;
dp[A][B] = maxCount;
}
}
return maxCount;
}
static int maxBananaCnt( int A, int B, int C)
{
for ( int i = 0 ; i < 1001 ; i++)
for ( int j = 0 ; j < 3001 ; j++)
dp[i][j] = - 1 ;
return recBananaCnt(A, B, C);
}
public static void main (String[] args) {
int A = 1000 ;
int B = 3000 ;
int C = 1000 ;
System.out.println(maxBananaCnt(A, B, C));
}
}
|
Python3
dp = [[ - 1 for i in range ( 3001 )] for j in range ( 1001 )]
def recBananaCnt(A, B, C):
if (B < = A):
return 0
if (B < = C):
return B - A
if (A = = 0 ):
return B
if (dp[A][B] ! = - 1 ):
return dp[A][B]
maxCount = - 2 * * 32
tripCount = (( 2 * B) / / C) - 1 if (B % C = = 0 ) else (( 2 * B) / / C) + 1
for i in range ( 1 ,A + 1 ):
curCount = recBananaCnt(A - i, B - tripCount * i, C)
if (curCount > maxCount):
maxCount = curCount
dp[A][B] = maxCount
return maxCount
def maxBananaCnt(A, B, C):
return recBananaCnt(A, B, C)
A = 1000
B = 3000
C = 1000
print (maxBananaCnt(A, B, C))
|
C#
using System;
public class GFG {
static int [, ] dp = new int [1001, 3001];
static int recBananaCnt( int A, int B, int C)
{
if (B <= A) {
return 0;
}
if (B <= C) {
return B - A;
}
if (A == 0) {
return B;
}
if (dp[A, B] != -1) {
return dp[A, B];
}
int maxCount = Int32.MinValue;
int tripCount = B % C == 0 ? ((2 * B) / C) - 1
: ((2 * B) / C) + 1;
for ( int i = 1; i <= A; i++) {
int curCount
= recBananaCnt(A - i, B - tripCount * i, C);
if (curCount > maxCount) {
maxCount = curCount;
dp[A, B] = maxCount;
}
}
return maxCount;
}
static int maxBananaCnt( int A, int B, int C)
{
for ( int i = 0; i < 1001; i++)
for ( int j = 0; j < 3001; j++)
dp[i, j] = -1;
return recBananaCnt(A, B, C);
}
public static void Main( string [] args)
{
int A = 1000;
int B = 3000;
int C = 1000;
Console.WriteLine(maxBananaCnt(A, B, C));
}
}
|
Javascript
<script>
let dp = new Array(1001);
for (let i = 0; i < dp.length; i++)
{
dp[i] = ( new Array(3001).fill(-1))
}
function recBananaCnt(A, B, C)
{
if (B <= A) {
return 0;
}
if (B <= C) {
return B - A;
}
if (A == 0) {
return B;
}
if (dp[A][B] != -1) {
return dp[A][B];
}
let maxCount = Number.MIN_VALUE;
let tripCount = B % C == 0 ? Math.floor((2 * B) / C) - 1
: Math.floor((2 * B) / C) + 1;
for (let i = 1; i <= A; i++) {
let curCount
= recBananaCnt(A - i,
B - tripCount * i, C);
if (curCount > maxCount) {
maxCount = curCount;
dp[A][B] = maxCount;
}
}
return maxCount;
}
function maxBananaCnt(A, B, C) {
return recBananaCnt(A, B, C);
}
let A = 1000;
let B = 3000;
let C = 1000;
document.write(maxBananaCnt(A, B, C));
</script>
|
Time Complexity: O(A*A*B)
Auxiliary Space: O(A*B)
Share your thoughts in the comments
Please Login to comment...