Search code examples
c++recursioncoin-change

What are the base cases for Coin Change using Recursion?


I am basically trying to solve the coin change problem through recursion and here is what i have so far -:

#include<iostream>
#include<conio.h>
using namespace std;

int a[]={1,2,5,10,20,50,100,200},count=0;

//i is the array index we are working at
//a[] contains the list of the denominations
//count keeps track of the number of possibilities

void s(int i,int sum) //the function that i wrote
{
    if (!( i>7 || sum<0 || (i==7 && sum!=0) )){

    if (sum==0) ++count; 

    s(i+1,sum);
    s(i,sum-a[i]);

    }
}


int c(int sum,int  i ){  //the function that I took from the algorithmist
    if (sum == 0)
        return 1;
    if (sum < 0)
        return 0;
    if (i <= 0 && sum > 0 )
        return 1;

    return (c( sum - a[i], i ) + c( sum, i - 1 ));
}
int main()
{
    int a;
    cin>>a;

    s(0,a);
    cout<<c(a,7)<<endl<<count;

    getch();
    return 0;
}

The first function that is s(i,sum) has been written by me and the second function that is c(sum,i) has been taken from here - (www.algorithmist.com/index.php/Coin_Change).

The problem is that count always return a way higher value than expected. However, the algorithmist solution gives a correct answer but I cannot understand this base case

if (i <= 0 && sum > 0 ) return 1;

If the index (i) is lesser than or equal to zero and sum is still not zero shouldn't the function return zero instead of one?

Also I know that the algorithmist solution is correct because on Project Euler, this gave me the correct answer.


Solution

  • I guess that your problem is "Assuming that I have unlimited support of coins, on how many ways can I change the given sum"? The algoritimists solution you gave assumes also, that the smallest denomination is 1. Otherwise it will won't work correctly. Now your question:

    if (i <= 0 && sum > 0 ) return 1;
    

    Notice, that the only possibility that i<0 is that you called it with this value - no recursive call will be made with negative value of i. Such case (i<0) is an error so no result is proper (maybe assertion or exception would be better). Now if i=0, assuming that at index 0 there is coin of value 1 means that there is only one way to exchange sum with this denomination - give sum coins of value 1. Right?

    After a moment of thought I found out how to remove assumption that a[0] == 1. Change

    if (i <= 0 && sum > 0 ) return 1;
    

    into

    if (i <= 0 && sum > 0 ) return sum % a[0] == 0 ? 1 : 0;