给定一个值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。
1)最佳子结构
要计算解决方案的总数,我们可以将所有解决方案分为两组。
1)不包含第m个硬币(或Sm)的解决方案。
2)包含至少1 Sm的溶液。
设count(S [],m,n)为计算解数的函数,则可以写为count(S [],m-1,n)和count(S [],m, n-Sm)。
因此,该问题具有最佳的子结构属性,因为可以使用子问题的解决方案来解决该问题。
2)重叠子问题
以下是硬币更改问题的简单递归实现。该实现仅遵循上述递归结构。
C++
// Recursive C program for
// coin change problem.
#include
// Returns the count of ways we can
// sum S[0...m-1] coins to get sum n
int count( int S[], int m, int n )
{
// If n is 0 then there is 1 solution
// (do not include any coin)
if (n == 0)
return 1;
// If n is less than 0 then no
// solution exists
if (n < 0)
return 0;
// If there are no coins and n
// is greater than 0, then no
// solution exist
if (m <=0 && n >= 1)
return 0;
// count is sum of solutions (i)
// including S[m-1] (ii) excluding S[m-1]
return count( S, m - 1, n ) + count( S, m, n-S[m-1] );
}
// Driver program to test above function
int main()
{
int i, j;
int arr[] = {1, 2, 3};
int m = sizeof(arr)/sizeof(arr[0]);
printf("%d ", count(arr, m, 4));
getchar();
return 0;
}
Python3
# Recursive Python3 program for
# coin change problem.
# Returns the count of ways we can sum
# S[0...m-1] coins to get sum n
def count(S, m, n ):
# If n is 0 then there is 1
# solution (do not include any coin)
if (n == 0):
return 1
# If n is less than 0 then no
# solution exists
if (n < 0):
return 0;
# If there are no coins and n
# is greater than 0, then no
# solution exist
if (m <=0 and n >= 1):
return 0
# count is sum of solutions (i)
# including S[m-1] (ii) excluding S[m-1]
return count( S, m - 1, n ) + count( S, m, n-S[m-1] );
# Driver program to test above function
arr = [1, 2, 3]
m = len(arr)
print(count(arr, m, 4))
# This code is contributed by Smitha Dinesh Semwal
C#
// Recursive C# program for
// coin change problem.
using System;
class GFG
{
// Returns the count of ways we can
// sum S[0...m-1] coins to get sum n
static int count( int []S, int m, int n )
{
// If n is 0 then there is 1 solution
// (do not include any coin)
if (n == 0)
return 1;
// If n is less than 0 then no
// solution exists
if (n < 0)
return 0;
// If there are no coins and n
// is greater than 0, then no
// solution exist
if (m <=0 && n >= 1)
return 0;
// count is sum of solutions (i)
// including S[m-1] (ii) excluding S[m-1]
return count( S, m - 1, n ) +
count( S, m, n - S[m - 1] );
}
// Driver program
public static void Main()
{
int []arr = {1, 2, 3};
int m = arr.Length;
Console.Write( count(arr, m, 4));
}
}
// This code is contributed by Sam007
PHP
= 1)
return 0;
// count is sum of solutions (i)
// including S[m-1] (ii) excluding S[m-1]
return coun($S, $m - 1,$n ) +
coun($S, $m, $n - $S[$m - 1] );
}
// Driver Code
$arr = array(1, 2, 3);
$m = count($arr);
echo coun($arr, $m, 4);
// This code is contributed by Sam007
?>
Javascript
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 enteries 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 enteries 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;
}
Java
/* Dynamic Programming Java implementation of Coin
Change problem */
import java.util.Arrays;
class CoinChange
{
static long countWays(int S[], int m, int n)
{
//Time complexity of this function: O(mn)
//Space Complexity of this function: O(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)
long[] table = new long[n+1];
// Initialize all table values as 0
Arrays.fill(table, 0); //O(n)
// 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
Python
# Dynamic Programming Python implementation of Coin
# Change problem
def count(S, m, n):
# We need n+1 rows as the table is constructed
# in bottom up manner using the base case 0 value
# case (n = 0)
table = [[0 for x in range(m)] for x in range(n+1)]
# Fill the entries for 0 value case (n = 0)
for i in range(m):
table[0][i] = 1
# Fill rest of the table entries in bottom up manner
for i in range(1, n+1):
for j in range(m):
# Count of solutions including S[j]
x = table[i - S[j]][j] if i-S[j] >= 0 else 0
# Count of solutions excluding S[j]
y = table[i][j-1] if j >= 1 else 0
# total count
table[i][j] = x + y
return table[n][m-1]
# Driver program to test above function
arr = [1, 2, 3]
m = len(arr)
n = 4
print(count(arr, m, n))
# This code is contributed by Bhavya Jain
C#
/* Dynamic Programming C# implementation of Coin
Change problem */
using System;
class GFG
{
static long countWays(int []S, int m, int n)
{
//Time complexity of this function: O(mn)
//Space Complexity of this function: O(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 = new int[n+1];
// Initialize all table values as 0
for(int i = 0; i < table.Length; i++)
{
table[i] = 0;
}
// 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 < m; i++)
for (int j = S[i]; j <= n; j++)
table[j] += table[j - S[i]];
return table[n];
}
// Driver Function
public static void Main()
{
int []arr = {1, 2, 3};
int m = arr.Length;
int n = 4;
Console.Write(countWays(arr, m, n));
}
}
// This code is contributed by Sam007
PHP
= 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
$arr = array(1, 2, 3);
$m = count($arr);
$n = 4;
echo count1($arr, $m, $n);
// This code is contributed by mits
?>
Javascript
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
Java
public static 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[]=new int[n+1];
// 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
Python
# Dynamic Programming Python implementation of Coin
# Change problem
def count(S, m, 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)
# Initialize all table values as 0
table = [0 for k in range(n+1)]
# 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 i in range(0,m):
for j in range(S[i],n+1):
table[j] += table[j-S[i]]
return table[n]
# Driver program to test above function
arr = [1, 2, 3]
m = len(arr)
n = 4
x = count(arr, m, n)
print (x)
# This code is contributed by Afzal Ansari
C#
// Dynamic Programming C# implementation
// of Coin Change problem
using System;
class GFG
{
static 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 = new int[n + 1];
// 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 < m; i++)
for(int j = S[i]; j <= n; j++)
table[j] += table[j - S[i]];
return table[n];
}
// Driver Code
public static void Main()
{
int []arr = {1, 2, 3};
int m = arr.Length;
int n = 4;
Console.Write(count(arr, m, n));
}
}
// This code is contributed by Raj
PHP
Javascript
输出 :
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)
/ \
/ \
. .
由于再次调用了相同的问题,因此此问题具有“重叠子问题”属性。因此,硬币更改问题具有动态编程问题的两个属性(请参阅此内容)。像其他典型的动态编程(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 enteries 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 enteries 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;
}
Java
/* Dynamic Programming Java implementation of Coin
Change problem */
import java.util.Arrays;
class CoinChange
{
static long countWays(int S[], int m, int n)
{
//Time complexity of this function: O(mn)
//Space Complexity of this function: O(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)
long[] table = new long[n+1];
// Initialize all table values as 0
Arrays.fill(table, 0); //O(n)
// 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
Python
# Dynamic Programming Python implementation of Coin
# Change problem
def count(S, m, n):
# We need n+1 rows as the table is constructed
# in bottom up manner using the base case 0 value
# case (n = 0)
table = [[0 for x in range(m)] for x in range(n+1)]
# Fill the entries for 0 value case (n = 0)
for i in range(m):
table[0][i] = 1
# Fill rest of the table entries in bottom up manner
for i in range(1, n+1):
for j in range(m):
# Count of solutions including S[j]
x = table[i - S[j]][j] if i-S[j] >= 0 else 0
# Count of solutions excluding S[j]
y = table[i][j-1] if j >= 1 else 0
# total count
table[i][j] = x + y
return table[n][m-1]
# Driver program to test above function
arr = [1, 2, 3]
m = len(arr)
n = 4
print(count(arr, m, n))
# This code is contributed by Bhavya Jain
C#
/* Dynamic Programming C# implementation of Coin
Change problem */
using System;
class GFG
{
static long countWays(int []S, int m, int n)
{
//Time complexity of this function: O(mn)
//Space Complexity of this function: O(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 = new int[n+1];
// Initialize all table values as 0
for(int i = 0; i < table.Length; i++)
{
table[i] = 0;
}
// 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 < m; i++)
for (int j = S[i]; j <= n; j++)
table[j] += table[j - S[i]];
return table[n];
}
// Driver Function
public static void Main()
{
int []arr = {1, 2, 3};
int m = arr.Length;
int n = 4;
Console.Write(countWays(arr, m, n));
}
}
// This code is contributed by Sam007
的PHP
= 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
$arr = array(1, 2, 3);
$m = count($arr);
$n = 4;
echo count1($arr, $m, $n);
// This code is contributed by mits
?>
Java脚本
输出:
4
时间复杂度: O(mn)
以下是方法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
Java
public static 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[]=new int[n+1];
// 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
Python
# Dynamic Programming Python implementation of Coin
# Change problem
def count(S, m, 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)
# Initialize all table values as 0
table = [0 for k in range(n+1)]
# 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 i in range(0,m):
for j in range(S[i],n+1):
table[j] += table[j-S[i]]
return table[n]
# Driver program to test above function
arr = [1, 2, 3]
m = len(arr)
n = 4
x = count(arr, m, n)
print (x)
# This code is contributed by Afzal Ansari
C#
// Dynamic Programming C# implementation
// of Coin Change problem
using System;
class GFG
{
static 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 = new int[n + 1];
// 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 < m; i++)
for(int j = S[i]; j <= n; j++)
table[j] += table[j - S[i]];
return table[n];
}
// Driver Code
public static void Main()
{
int []arr = {1, 2, 3};
int m = arr.Length;
int n = 4;
Console.Write(count(arr, m, n));
}
}
// This code is contributed by Raj
的PHP
Java脚本
输出:
4