使用递归进行硬币更改的基本情况是什么

What are the base cases for Coin Change using Recursion?

本文关键字:基本情况 是什么 硬币 递归      更新时间:2023-10-16

我基本上试图通过递归来解决硬币变化问题,这是我到目前为止所拥有的 - :

#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;
}

第一个函数 s(i,sum) 是由我编写的,第二个函数 c(sum,i) 是从这里获取的 - (www.algorithmist.com/index.php/Coin_Change)。

问题是计数总是返回比预期更高的值。但是,算法解决方案给出了正确的答案,但我无法理解这种基本情况

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

如果索引 (i) 小于或等于零并且总和仍然不为零,函数不应该返回零而不是 1 吗?

我也知道算法的解决方案是正确的,因为在欧拉项目中,这给了我正确的答案。

我想你的问题是"假设我对硬币有无限的支持,我可以通过多少种方式改变给定的总和"?你给出的算法学家解决方案也假设最小面额是1。否则它将无法正常工作。现在你的问题:

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

请注意,i<0的唯一可能性是您使用此值调用它 - 不会进行负值 i 的递归调用。这种情况(i<0)是一个错误,所以没有结果是合适的(也许断言或异常会更好)。现在,如果i=0,假设在指数0有价值硬币1意味着只有一种方法可以sum与这种面额交换 - 给sum有价值的硬币1。右?

经过片刻的思考,我发现了如何消除a[0] == 1假设.改变

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

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

我认为算法偏向于面额的选择,并假设只有一枚最小面额的硬币。考虑一个正确性的反例,即没有 2 个硬币,只有 1,5 个,...并且返回的目标是 4:

 (4,1)
    (-1,1)  -> cut, sum<0 a[1]==5
    (4,0)   -> i==0 => 1

要么是这样,要么是你错误地实现了算法(会有一个错误吗?它可以是i<0,还是原始数组是从 1 开始的?