上篇文章我们讲述了如何选出最小硬币组合,那么这期我给大家带来了硬币第二种类型----输出所有可能的硬币组合。
给道例题,有五种硬币(1分,5分,10分,25分,50分),数量无限多,,给定一个金额,输出所有组合方案数。
思考这道题,我们跟上一篇文章进行比较,上一篇是让们我选出最小硬币组合,这道题是让我们输出全部的结果数,我们在做最小硬币组合的时候,找到的状态转移方程如下....
dp[j] = min(dp[j] , dp[j - w[i]] + 1);
因为两种去向选出最小,所以将这两种去向进行比较,选出最小值,那么输出所有的方案不就是将这两种去向相加不就得到了全部的组合了吗,那么见状态方程....
dp[j] = dp[j] + dp[j - w[i]];
咱们这里的dp[j]数组的含义为索要金额j对应的组合方案数,如果读者对于这里为何不+1有疑问,麻烦仔细想一想上面的dp数组的含义与这里的dp数组的含义,含义不一样,上道题是因为我们要的是最小硬币数量所以要加一,而这里因为要方案数,所以两个方案数相加即可这里咱们也可以换一种理解方法,j金额对应的dp数组是逐渐递推而来的,当前的j对应的组合方案数是不是代表自己本身的组合再加上每种硬币w[i]对应的组合方案数,这样理解也是最好不过的,如果还是无法理解,那就将其打印出来再对比分析吧,实践是检验的方式,下面看代码....
#include<stdio.h>
const int N = 1000;
int w[N];
int dp[N];
int money;
int main()
{
scanf("%d",&money);
for(int i = 0;i < 5;i++)
{
scanf("%d",&w[i]);
}
dp[0] = 1;
for(int i = 0;i < 5;i++)
{
for(int j = w[i];j <= money;j++)
{
dp[j] = dp[j] + dp[j - w[i]];
}
}
printf("%d",dp[money]);
return 0;
}
咱们看一下这里的初始化为何是dp[0] = 1;可以对于其dp数组含义分析,这里的含义是零金额对应的组合数,组合数为1;如果还是不理解那就对于其代码理解,先给一分的硬币,如果给与dp[0] = 0,那么dp[1] = dp[1] + dp[0] = 0;而dp[1] = 1,所以这里要改变dp[0] = 1才能使对应的值正确。
好了,今天的分享到此结束,下期给大家带来硬币问题(3),对硬币的数量加以限制我们应该如何做?既然看到这里了不妨给个三连吧,感谢老铁收看,我们下次再见啦。