给你一个整数数组 coins
,表示不同面额的硬币;以及一个整数 amount
,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1
。
你可以认为每种硬币的数量是无限的。
输入:coins =[1, 2, 5]
, amount =11
输出:3
解释:11 = 5 + 5 + 1
示例 2:
输入:coins =[2]
, amount =3
输出:-1
示例 3:
输入:coins = [1], amount = 0 输出:0
题目出处:力扣
代码:
#include<iostream>
#define N 100
using namespace std;
void f(int a[], int n, int m)
{
if (n == 0 || m == 0)
{
cout << "0" << endl;
return;
}
int dp[N] = { 0 };
for (int i = 1; i <= m; i++)
{
dp[i] = m + 1;
}
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (i >= a[j])
{
dp[i] = min(dp[i], dp[i - a[j]] + 1);
}
}
}
if (dp[n] == m + 1)
cout << -1 << endl;
else
cout<<dp[m]<<endl;
return;
}
int main()
{
int n = 0;
int m = 0;
int a[N] = { 0 };
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
cin >> m;
f(a, n, m);
return 0;
}
fi函数解释:
极限:n为0时与m为0时都退出函数
内部:因为dp[i]设置意义为当前钱总量为i时最少硬币个数,为了找到这个“最小”,需要把当前的dp[i]与之后的dp[i-a[j]]+1(a[j],即当前循环到的硬币值,dp[i-a[j]]表示减去这个币值后硬币数最少数,因为要加上当前这个币的数量所以加一),因为要比较,在最初比较时必须将dp[i](i>=1)设置为较大的数,但是dp[0]必须为0,以免影响结果。
循环:以a = [1, 2, 5]
, m= 11
为例子,
i=2,j=1时,满足i>=a[j],此时dp[2]=min(很大的数,dp[i-a[j]]+1)=dp[1]=2
i=2,j=2时,满足i>=a[j],此时dp[2]=min(dp[2](上面求的值),dp[i-a[j]])=min(2,dp[0]+1)=1
以上的dp[1],是i=1时求的,可以自己推