题目描述
给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。
如果无解,请返回-1.
输入
复制
[5,2,3],20
输出
复制
4
【思路】
经典的dp问题,每一轮研究新的硬币k的加入,能否使得之前组配sum的硬币总数减少
即 dp[sum]=min(dp[sum],dp[sum-k]+1) ①
注意点:
初始化dp[0]=0 dp[i]=-1 即没有组配方案
sum-k>=0 需要讨论,公式①需要在dp[sum]!=-1情况下,若等于-1 那没得选 dp[sum]=dp[sum-k]+1
class Solution {
public:
int minMoney(vector<int>& arr, int aim) {
// write code here
vector<int> dp(aim+1);//dp[i]表示组合成aim最少使用的硬币
for(int i=0;i<aim+1;i++)
dp[i]=-1;
if(arr.size()==0 || aim<0)
return -1;
// sort(arr.begin(),arr.end());//排序
dp[0]=0;
for(int i=0;i<arr.size();i++)
{
//每一轮研究一组更大面值硬币的加入能否减少硬币使用量
//分别查看j面值组配方案
for(int j=1;j<=aim;j++)
{
//对于当前研究总额j 如果比j小arr[i]的总额存在组配方案
//那么当前的dp更新
if((j-arr[i])>=0 && dp[j-arr[i]]!=-1)
{
if(dp[j]==-1)
dp[j]=dp[j-arr[i]]+1;
else
dp[j]=min(dp[j],dp[j-arr[i]]+1);
}
}
}
return dp[aim];
}
};