我基本上是试图通过递归来解决硬币变化问题,这是我到目前为止所做的 - :
#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)小于或等于零且sum仍然不为零,那么函数是否应该返回零而不是一个?
我也知道算法主义解决方案是正确的,因为在Project Euler上,这给了我正确答案。
答案 0 :(得分:0)
我认为算法偏向于选择面额,并假设只有一个最小面额的硬币。考虑作为正确性的反例,没有2个硬币,只有1.5,......而且要返回的目标是4:
(4,1)
(-1,1) -> cut, sum<0 a[1]==5
(4,0) -> i==0 => 1
或者你错误地实现了算法(可能有一个错误吗?可能是i<0
,还是原始数组是基于1的?)
答案 1 :(得分:0)
我猜你的问题是“假设我有无限制的硬币支持,我可以用多少种方式改变给定的金额”?
你给出的算法解决方案也假设,最小面额是1
。否则它将无法正常工作。
现在你的问题是:
if (i <= 0 && sum > 0 ) return 1;
请注意,i<0
是您用此值调用它的唯一可能性 - 不会使用负值i
进行递归调用。这种情况(i<0
)是一个错误,所以没有结果是正确的(可能断言或异常会更好)。
现在,如果i=0
,假设在索引0
处有值1
的硬币意味着只有一种方法可以用这个面额交换sum
- 给{{1} }值为sum
的硬币。正确?
经过一段时间的思考后,我发现了如何删除1
的假设。改变
a[0] == 1
到
if (i <= 0 && sum > 0 ) return 1;