1. 程式人生 > >美團筆試題(一)-[程式設計題] 拼湊錢幣

美團筆試題(一)-[程式設計題] 拼湊錢幣

[程式設計題] 拼湊錢幣

給你六種面額 1、5、10、20、50、100 元的紙幣,假設每種幣值的數量都足夠多,編寫程式求組成N元(N為0~10000的非負整數)的不同組合的個數。

輸入描述:

輸入包括一個整數n(1 ≤ n ≤ 10000)

輸出描述:

輸出一個整數,表示不同的組合方案數

輸入例子1:

1

輸出例子1:

1

分析:其中假設所有的錢幣總數為

V = V 0 , V 1 , V 2
, , V i
。總共有 i 種錢幣。我們用
" role="presentation" style="position: relative;"> d p [ i ] [ n ] 表示用 i 種錢幣表示組成 n 元的組合數。我們依次分析12元以內的硬幣組合數量。

當我們只使用1種硬幣的時候,所有的組合情況如下:

使用硬幣數 1 2 3 4 5 6 7 8 9 10 11
只使用1 1 1 1 1 1 1 1 1 1 1 1
1和5 1 1 1 1 2 2 2 2 2 3 3
1、5和10 1 1 1 1 2 2 2 2 2 4 4

依次往下。

當我們增加一種硬幣(硬幣5)的時候,組合的結果相對於只使用1來說是,在原有隻有1的統計基礎上行,增加 1 個5元硬幣輸出的組合情況 + 增加2個5元硬幣輸出得組合情況 + … + 直到增加到最大的 5 元硬幣數量為止。就如具體的取 n = 10 來說明。

當我們新增加一個5元硬幣時,使用硬幣5的所有次數取值範圍為 0 , 1 , 2 。其中 2 = m a x [ n 5 ]

我們分情況來考慮:

  1. 當使用0個5元時,就是上面用1組成數字n的情況;
  2. 當時用1個5元時,就是上面用1組成數字n-5的情況;
  3. 當使用2個5元時,就是上面用1組成數字n-2*5的情況。

所以,當使用1和5兩種硬幣表示數字n=10的時候,就是講上面的所有情況累加 d p [ 2 ] [ 10 ] = d p [ 1 ] [ 10 ] + d p [ 1 ] [ 5 ] + d p [ 1 ] [ 0 ] 。總結成通用的公式就如下所示

d p [ i + 1 ] [ n ] = i = 0 k d p [ i ] [ n i × v i + 1 ] k = 0 , 1 , , m a x [ n / v i + 1 ]

程式碼實現如下:

public class Solution {
    static int[] values = {1,5,10,20,50,100};
    static int combine(int n) {
        n++; // 主要是需要多增加一個為0的時候空位,不然會出錯
        int[][] dp = new int[values.length][n];
        for (int i = 0; i < n; i++) {
            dp[0][i] = 1;
        }
        for (int i = 1; i < values.length; i++) {
            for (int j = 0,k; j < n; j++) {
                k = j/values[i];
                while(k>=0){
                    dp[i][j] += dp[i-1][j-k*values[i]];
                    k--;
                }
                System.out.print(dp[i][j]+"\t");
            }
            System.out.println();
        }
        return dp[values.length-1][n-1];
    }
    public static void main(String[] args){
        System.out.println(combine(20));
    }
}