You have a stack overflow because your recursion depth is limited by only the size of your array and the number of pennies. And your stack state is reasonable in size.
One solution is to go with an explicit stack.
enum coins {
penny, nickle, dime, quarter, half,
coin_count
};
enum {
max_cash = 7495
};
struct coin_problem {
coins lowest_coin = penny;
int money = 0;
};
struct coin_cache {
unsigned long long solution[coin_count][max_cash+1];
coin_cache(){
for(auto& row:solution)
for(auto& val:row)
val=-1;
}
unsigned long long& set(coin_problem p){
return solution[p.lowest_coin][p.money];
}
unsigned long long get(coin_problem p)const{
if(p.lowest_coin==coin_count) return 0;
if(p.money==0) return 0;
return solution[p.lowest_coin][p.money];
}
};
unsigned long long count_solutions( std::vector<coin_problem>& vec, coin_cache& cache){
unsinged long lon retval = 0;
while(!vec.empty()){
auto cur = vec.back();
retval = cache.get[cur];
if (retval != -1) {
vec.pop_back();
continue;
}
++cur.lowest_coin;
auto op1 = cache.get[cur];
if (op1 == -1) vec.push_back(cur);
--cur.lowest_coin;
unsigned long long op2 = -1;
if(Cents[cur.lowest_coin] <= cur.money){
cur.money -= Cents[cur.lowest_coin];
op2 = cache.get[cur];
if (op2==-1) vec.push_back(cur);
cur.money += Cents[cur.lowest_coin];
} else {
op2 = 0;
}
if (op1 != -1 && op2 != -1){
retval = cache.set(cur) = op1+op2;
vec.pop_back();
}
}
return retval;
}
unsigned long long count_solutions( coin_problem p ){
auto pcache = std::make_unique<coin_cache>();
std::vector<coin_problem> todo = {p};
return count_solutions( todo, *pcache );
}
I tore your recursive solution up and gave it a manual stack.
For each entry in the stack of problems, we first see if there is a solution waiting in the cache. If so, we calculate it, and store it in the cache, and pop the problem. If the stack of problems is empty, we return it.
If not, we push sub problems to solve first onto the top if the stack, leaving our current problem to be solved later, and loop until the stack is empty.
As our manual stack exists on the free store (aka the heap) we are unlikely to experience a stack overflow on a desktop system.
This isn't perfectly efficient, as we can have more than one entry on the stack for each problem. But that should be at most a constand factor, and can be likely fixed by reordering the "recursion" to do the "deepest" call first. Or making the stack of problems a set of problems ordered by depth.
Another approach is to just solve every entry in the table, deepest first.