**Problem**

You are given an integer array `coins`

representing coins of different denominations and an integer `amount`

representing a total amount of money.

Return the `number of combinations`

that make up that amount. If that amount of money cannot be made up by any combination of the coins, return `0`

.

You may assume that you have an infinite number of each kind of coin.

###### Input

int: amount, int vector: coins[n]

###### Output

an integer representing the number of combinations that make up that amount

###### Constraints

`1 <= coins.length <= 300`

`1 <= coins[i] <= 5000`

`0 <= amount <= 5000`

###### Sample Input

coins = [1,2,5], amount = 5

###### Sample Output

4 Explanation: there are four ways to make up the amount: 5=5 5=2+2+1 5=2+1+1+1 5=1+1+1+1+1

###### Solution

This problem could be solved in polynomial time using Dynamic programming.

###### Dynamic Programming

This problem is similar to Coin Change problem, discussed here.

**Optimal Substructure (Bottom up approach)**

dp[j] represents the number of combinations that make up the amount j Now according to optimal substructure: for i = 0 to coins.size()-1: for j = coins[i] to amount: dp[j] = dp[j] + dp[j-coins[i]]

**Base case & Initialisation**

dp[0] = 1, number of ways to make sum = 0, is 1 (not including any coin) dp[j] = 0, if j > 0

###### Code Implementation

```
int change(int amount, vector<int>& coins) {
int n = (int) coins.size();
int dp[amount+1];
dp[0] = 1;
for(int i=1; i<=amount; i++) {
dp[i] = 0;
}
for(int i=0; i<n; i++) {
for (int j=coins[i]; j<=amount; j++) {
dp[j] += dp[j-coins[i]];
}
}
return dp[amount];
}
```

**Time complexity of the above solution is O(n*amount) (n is the size of coins vector) and auxiliary space required is O(amount).**