您的位置:首页 > 其它

换零钱的算法

2016-05-05 18:16 288 查看

换零钱的算法

问题来自SICP,描述如下

现在若干纸币,想要兑换成硬币。硬币面值有1, 5, 10, 25, 50分的硬币。什么,没有25分的,我说的是美元。。。

问有多少种组合方式

这是介绍线性递归这个概念的时候的一个例子,很有意思。

算法嘛,很朴素啊,其主要思想如下

回合制,就是一次递归

每一次都可以选择兑换一个面值最大的,或者不兑换

剩下的将进入下一轮兑换,直到剩下的钱数为0

scheme的代码就不贴上来了,太简单太抽象。我们还是用C++吧

#include<iomanip>
#include<iostream>
using namespace std;

int coin_value[]={0,1, 5, 10, 25, 50};
int coin_count[]={0,0, 0, 0, 0, 0};
int entry_count;
int* matrix;
int cc(int money, int coin_type,int lr)
{
int val = 0;
int vala = 0;
int valb = 0;
entry_count++;
//    cout<<"("<< setw(4) <<money<<","<< setw(4) <<coin_value[coin_type]<<")  ==> ";
if (lr==0)
{
int a = sizeof(coin_count);
memset(coin_count, 0, sizeof(coin_count));
}
if (money ==0)
{
val = 1;
}
else if ((money<0) || (coin_type==0))
{
val = 0;
}
//    else if (matrix[money*6+coin_type] >=0)
//    {
//        val = matrix[money*6+coin_type];
//    }
else
{
vala = cc(money, coin_type-1,0);
valb = cc(money-coin_value[coin_type], coin_type, 1);
val = vala + valb;
if (vala == 0) coin_count[coin_type] += valb;
else           coin_count[coin_type] = valb;
if (money >=0 )matrix[money*6+coin_type] = val;
}

//    cout<<"("<< setw(4) <<money<<","<< setw(4) <<coin_value[coin_type]<<", ";
//    cout<<setw(4) << val <<", "<<(lr==0? "left" :"right") <<")"<<endl;
return val;
}

int main()
{
int money = 100;
matrix = new int[(money+1)*sizeof(coin_value)/sizeof(int)];
memset(matrix, -1, (money+1)*sizeof(coin_value));
entry_count = 0;
cout <<"method = " <<cc(money, 5, 0);
cout << ", calls= "<<entry_count<<endl;
delete[] matrix;
return 0;
}


上面代码用标准递归,被注释掉的那块else if代码是查找已经计算过的节点的值,用来减少递归调用次数。

金额(美分)10100200500
组合方式4292243559576
查找表方式递归次数312895811457
简单递归方式递归次数411549922958912822611
可以看到用查找表方式,算法的时间复杂度是O(n),简单递归的时间复杂度是O(n^m)。不过查找表方式 空间复杂度是O(n*m),简单递归的空间复杂度是O(n+m)。其中,n是金额,m是硬币种类数。

那么,如果我们想知道每种组合的具体配置,how?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: