📜  硬币找零的C程序| DP-7

📅  最后修改于: 2022-05-13 01:57:39.362000             🧑  作者: Mango

硬币找零的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 了解更多详情!