零钱兑换1【DP】
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
你可以认为每种硬币的数量是无限的。
动态规划三要素:
1.重叠子问题
2.最优子结构
3.状态转移方程
3.1明确 base case
3.2明确 状态
3.3明确 选择
3.4定义 dp数组
这题的最优子结构:
amount=11的最少数问题与amount=10的最少数问题是相互独立的。
状态转移:
1).base case : amount=0 , 最少数=0
2).状态 : 金钱数量无限,给定amount,那么amount会不断向base case 靠近,所以说唯一的状态就是amount
3).选择 : 就是导致状态改变的行为,导致amount改变就是选择面值来凑amount
4).dp : dp[n] 返回 amount=n的最少金钱数量
方程:
\[dp(n) = \left\{\begin{matrix}
0,&n=0 \\
min(dp(n),1+dp(n-x)&n>0
\end{matrix}\right.\]
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int dp[10000000];
for(int i=0;i<10000000;i++)
dp[i] = 10000000;
if(amount < 0)
return -1;
dp[0] = 0;
for(int i=1;i<=amount;i++)
{
for(int j = 0;j<coins.size();j++)
{
if(i-coins[j]>=0)
dp[i] = min(dp[i],dp[i- coins[j]]+1);
}
}
if(dp[amount] >= 10000000)
return -1;
else
return dp[amount];
/*
long long sum = 1;
for(int i=0;i<31;i++)
sum = sum*2;
return sum;*/
}
};