方法一 转自http://www.cnblogs.com/python27/archive/2013/09/05/3303721.html
动态规划的方法,是将m*n(m表示硬币的种类,n表示所要组成的和)的辅助数组,
个人认为这种方法的缺点是 较难理解,计算时间和辅助空间占用较多
方法二 参考http://blog.csdn.net/randyjiawenjie/article/details/6335208
这种方法是用递归的方式实现,个人觉得此方法在克服动态规划的缺陷上有较好的表现
下面是对两种算法的实现
#include <stdio.h>
#include <list>
#include <vector>
using namespace std;
list<int> myList;
int count = 0;
/*********************************
* numbers Combinations: using recursive algorithm
* Basic idea:
* 输入两个整数n和sum,从数列1,2,3,……n中随意取几个数,使其和等于sum。
* 要求将所有的可能组合列出来
**********************************/
void findSum(int sum,int n)
{
if(n<1 || sum <1)
{
return ;
}
if(sum > n)
{
myList.push_back(n);
findSum(sum-n,n-1);
myList.pop_back();
findSum(sum,n-1);
}
else if(sum == n)
{
count++;
list<int>::iterator it = myList.begin();
while(it != myList.end())
{
printf(" %d",*it++);
}
printf(" %d",n);
printf(" count = %d\n",count);
}
else{
}
}
void findRecursive(int sum,int n[],int index)
{
if(index < 0 )
{
return ;
}
if(sum >= n[index])
{
for(int i=1;i<= sum/n[index];i++)
{//printf(" sum=%d,i*n[index]=%d \n",sum,i*n[index]);
myList.push_back(i);
myList.push_back('*');
myList.push_back(n[index]);
if(sum-i*n[index] == 0)
{
count++;
list<int>::iterator it = myList.begin();
while(it != myList.end())
{
if(*it != 42)
printf(" %d",*it);
else
printf("*");
it++;
}
printf(" count = %d\n",count);
}
findRecursive(sum-i*n[index],n,index-1);
myList.pop_back();
myList.pop_back();
myList.pop_back();
}
findRecursive(sum,n,index-1);
}
else if(sum == n[index])
{
count++;
list<int>::iterator it = myList.begin();
while(it != myList.end())
{
if(*it != 42)
printf(" %d",*it);
else
printf("*");
it++;
}
if(sum != 0)
printf(" %d",n[index]);
printf(" count = %d\n",count);
}
else{
}
}
/****************************************************************
* coin Combinations: using dynamic programming
*
* Basic idea:
* dp[i][j] = sum(dp[i-1][j-k*coins[i-1]]) for k = 1,2,..., j/coins[i-1]
* dp[0][j] = 1 for j = 0, 1, 2, ..., sum
*
* Input:
* coins[] - array store all values of the coins
* coinKinds - how many kinds of coins there are
* sum - the number you want to construct using coins
*
* Output:
* the number of combinations using coins construct sum
*
* Usage:
* c[3] = {1, 2, 5};
* int result = coinCombinations(c, 3, 10);
*
****************************************************************/
int findDP(int sum,int coins[], int coinKinds)
{
// 2-D array using vector: is equal to: dp[coinKinds+1][sum+1] = {0};
vector<vector<int> > dp(coinKinds+1);
int i=0;
for(i=0;i<=coinKinds;i++)
{
dp[i].resize(sum+1);
}
for(i = 0; i<=coinKinds;i++)
{
for(int j=0;j<=sum;j++)
{
dp[i][j] = 0;
}
}
//init: dp[i][0] = 1; i = 0, 1, 2 ..., coinKinds
//Notice: dp[0][0] must be 1, althongh it make no sense that
//using 0 kinds of coins construct 0 has one way. but it the foundation
//of iteration. without it everything based on it goes wrong
for(i=0;i<=coinKinds;i++)
{
dp[i][0] = 1;
}
//iteration: dp[i][j]= sum(dp[i-1][j-k*coins[i-1])
//k = 0,1,2,3,...,j/coins[i-1]
for (i = 1; i <= coinKinds; ++i)
{
for (int j = 1; j <= sum; ++j)
{
dp[i][j] = 0;
for (int k = 0; k <= j / coins[i-1]; ++k)
{
dp[i][j] += dp[i-1][j - k * coins[i-1]];
}
}
}
return dp[coinKinds][sum];
}
int main()
{
int m,n;
int i,j;
int a[]={5,2,1};
m = 20,n=9;
// findSum(10,n);
findRecursive(10,a,2);
// count = findDP(10,a,3);
printf("find %d times\n",count);
return 0;
}