硬币找零的C程序| DP-7
给定一个 N 值,如果我们想用 N 美分找零,并且我们有无限供应 S = { S1, S2, .. , Sm} 价值的硬币,我们可以用多少种方法来找零?硬币的顺序无关紧要。
例如,对于 N = 4 和 S = {1,2,3},有四种解:{1,1,1,1},{1,1,2},{2,2},{1, 3}。所以输出应该是 4。对于 N = 10 和 S = {2, 5, 3, 6},有五种解决方案:{2,2,2,2,2},{2,2,3,3}, {2,2,6}、{2,3,5} 和 {5,5}。所以输出应该是5。
输出 :
4
需要注意的是,上述函数一次又一次地计算相同的子问题。对于 S = {1, 2, 3} 和 n = 5,请参见以下递归树。
函数C({1}, 3) 被调用两次。如果我们绘制完整的树,那么我们可以看到有很多子问题被多次调用。
C() --> count()
C({1,2,3}, 5)
/ \
/ \
C({1,2,3}, 2) C({1,2}, 5)
/ \ / \
/ \ / \
C({1,2,3}, -1) C({1,2}, 2) C({1,2}, 3) C({1}, 5)
/ \ / \ / \
/ \ / \ / \
C({1,2},0) C({1},2) C({1,2},1) C({1},3) C({1}, 4) C({}, 5)
/ \ / \ /\ / \
/ \ / \ / \ / \
. . . . . . C({1}, 3) C({}, 4)
/ \
/ \
. .
由于再次调用相同的子问题,此问题具有重叠子问题属性。所以硬币找零问题具有动态规划问题的两个属性(参见this和this)。与其他典型的动态规划(DP)问题一样,通过以自下而上的方式构造临时数组 table[][] 可以避免相同子问题的重新计算。
动态规划解决方案
C++
// C++ program for coin change problem.
#include
using namespace std;
int count( int S[], int m, int n )
{
int i, j, x, y;
// We need n+1 rows as the table
// is constructed in bottom up
// manner using the base case 0
// value case (n = 0)
int table[n + 1][m];
// Fill the entries for 0
// value case (n = 0)
for (i = 0; i < m; i++)
table[0][i] = 1;
// Fill rest of the table entries
// in bottom up manner
for (i = 1; i < n + 1; i++)
{
for (j = 0; j < m; j++)
{
// Count of solutions including S[j]
x = (i-S[j] >= 0) ? table[i - S[j]][j] : 0;
// Count of solutions excluding S[j]
y = (j >= 1) ? table[i][j - 1] : 0;
// total count
table[i][j] = x + y;
}
}
return table[n][m - 1];
}
// Driver Code
int main()
{
int arr[] = {1, 2, 3};
int m = sizeof(arr)/sizeof(arr[0]);
int n = 4;
cout << count(arr, m, n);
return 0;
}
// This code is contributed
// by Akanksha Rai(Abby_akku)
C
// C program for coin change problem.
#include
int count( int S[], int m, int n )
{
int i, j, x, y;
// We need n+1 rows as the table is constructed
// in bottom up manner using the base case 0
// value case (n = 0)
int table[n+1][m];
// Fill the entries for 0 value case (n = 0)
for (i=0; i= 0)? table[i - S[j]][j]: 0;
// Count of solutions excluding S[j]
y = (j >= 1)? table[i][j-1]: 0;
// total count
table[i][j] = x + y;
}
}
return table[n][m-1];
}
// Driver program to test above function
int main()
{
int arr[] = {1, 2, 3};
int m = sizeof(arr)/sizeof(arr[0]);
int n = 4;
printf(" %d ", count(arr, m, n));
return 0;
}
C
int count( int S[], int m, int n )
{
// table[i] will be storing the number of solutions for
// value i. We need n+1 rows as the table is constructed
// in bottom up manner using the base case (n = 0)
int table[n+1];
// Initialize all table values as 0
memset(table, 0, sizeof(table));
// Base case (If given value is 0)
table[0] = 1;
// Pick all coins one by one and update the table[] values
// after the index greater than or equal to the value of the
// picked coin
for(int i=0; i
C
// C program for coin change problem.
#include
int count( int S[], int m, int n )
{
int i, j, x, y;
// We need n+1 rows as the table is constructed
// in bottom up manner using the base case 0
// value case (n = 0)
int table[n+1][m];
// Fill the entries for 0 value case (n = 0)
for (i=0; i= 0)? table[i - S[j]][j]: 0;
// Count of solutions excluding S[j]
y = (j >= 1)? table[i][j-1]: 0;
// total count
table[i][j] = x + y;
}
}
return table[n][m-1];
}
// Driver program to test above function
int main()
{
int arr[] = {1, 2, 3};
int m = sizeof(arr)/sizeof(arr[0]);
int n = 4;
printf(" %d ", count(arr, m, n));
return 0;
}
下面是方法2的简化版。这里需要的辅助空间只有O(n)。
C
int count( int S[], int m, int n )
{
// table[i] will be storing the number of solutions for
// value i. We need n+1 rows as the table is constructed
// in bottom up manner using the base case (n = 0)
int table[n+1];
// Initialize all table values as 0
memset(table, 0, sizeof(table));
// Base case (If given value is 0)
table[0] = 1;
// Pick all coins one by one and update the table[] values
// after the index greater than or equal to the value of the
// picked coin
for(int i=0; i
请参阅有关硬币变化的完整文章 | DP-7 了解更多详情!