【发布时间】:2015-01-23 03:15:24
【问题描述】:
我基本上是在尝试通过递归来解决硬币找零问题,这就是我目前所拥有的 -:
#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) .
问题在于 count 总是返回比预期更高的值。但是,算法专家的解决方案给出了正确的答案,但我无法理解这个基本情况
if (i <= 0 && sum > 0 ) return 1;
如果索引 (i) 小于或等于 0,并且 sum 仍然不为零,那么函数不应该返回零而不是一吗?
我也知道算法专家的解决方案是正确的,因为在Project Euler,这给了我正确的答案。
【问题讨论】:
-
你能用英文简单描述一下你的算法吗?这是第一步,从那里您可以实施。我不会使用你复制的算法,也不会使用你实现的算法……但我可以用简单的步骤来描述它,从那里它很容易实现。
-
@DavidRodríguez-dribeas 好吧,我可以根据递归树中分支/节点的打开来描述 - 对于面额数组中的每个成员,我打开一个节点,其中包含该元素sum[i.e s(i,sum-a[i])] 和另一个该元素不包含在 sum 中并且函数移动到数组的下一个元素 [i.e. s(i+1,sum)]。这样每次总和变为零时,我都会增加计数。我做错了什么?
-
该描述与简单的英语相差甚远,考虑到您正在向您的祖母解释问题和解决方案,您如何提供确切的更改? (通过将问题简化为更小)。例如,要返回价值 X 的零钱,选择最大面额的值,如果 X 大于面额 D,则返回该面额的硬币并解决 X-D 的问题,如果 X 小于 D,则没有更多的硬币可以产生该面额,并尝试通过使用去除 D 的面额子集返回 X。
-
... 这两个递归步骤可以保证减少问题,或者通过返回较小的值或使用较小的面额集,所以这很好。你什么时候需要停止,当然,如果要返回的值是 0,或者如果你用完了面额(你的面额集不会出现这种情况)。看?简单的英语,没有搜索树或数组或函数......
标签: c++ recursion coin-change