零钱兑换问题

//给你一个整数数组coins,表示不同面额的硬币;以及一个整数amount, 表示总金额
//计算并返回可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 - 1.
//你可以认为每种硬币的数量是无限的。

#include <iostream>
#include <vector>

using namespace std;

int changeCoins(vector<int>& coins, int amount)
{
	// 初始化数组 dp,长度为 amount + 1,因为在 dp 数组中还会存储金额为 0 的情况
	 // dp[i] 表示想要凑齐 i 元需要的最少硬币个数
	 // dp[0] 表示想要凑齐 0 元需要的最少硬币个数
	 // dp[1] 表示想要凑齐 1 元需要的最少硬币个数
	 // dp[14] 表示想要凑齐 14 元需要的最少硬币个数
	 // 首先将数组 dp 里面的值都初始化为 -1
	 // -1 表示当前的金额还没有找到需要的最少硬币个数
	vector<int> dp(amount + 1, -1);

	// dp[0] 表示想要凑齐 0 元需要的最少硬币个数
	dp[0] = 0;

	//for循环填充dp[0]到dp[amount]的值,得到dp[amount]最优解
	for (int i = 1; i <= amount; i++)
	{
		//for循环遍历你拥有的零钱的种类,确定哪些零钱能用来拼凑amount的值,并且确定最优的dp[i]的值(最少的硬币数目),即dp[i]的值最小
		for (int j = 0; j < coins.size(); j++)
		{
			//只有硬币的值小于等于当前i的值才能用来拼凑i的值,,,,且如果当前的硬币的值小于i的值的时候,要确保剩余的部分(i - coins[j])是可以拼凑出来的.即
			//dp[i - coins[j]]的值不为-1,dp数组的值是从小到大填充的,所以当看i元可不可以拼凑的时候,dp[i - coins[j]]的值必定是有值的,已经处理过的.
			if (coins[j] <= i && dp[i - coins[j]] != -1)
			{

				//到了这里表示i元是可以拼凑出来的,
				//如果dp[i]的值为-1则表是这个位置的dp第一次遇到可以拼凑成功的时刻,直接dp[i]= 1(当前遍历的这个硬币) + dp[i - coins[j]](除去当前硬币,剩余的钱需要的硬币数)
				//如果dp[i]的值不为-1则表是这个位置的dp不是第一次遇到可以拼凑成功的时刻,比较当前需要的硬币数1(当前遍历的这个硬币) + dp[i - coins[j]](除去当前硬币,剩余的钱需要的硬币数)
				//和之前记录的需要的硬币数dp[i],如果1+ dp[i - coins[j]]更小,就用1+ dp[i - coins[j]]把dp[i]更新掉
				if (dp[i] == -1 || dp[i] > 1 + dp[i - coins[j]])
				{
					dp[i] = 1 + dp[i - coins[j]];
				}
			}
		}
	}

	return dp[amount];


}

int main()
{
	vector<int> coins = { 1, 2, 5, 7, 10 };

	int amount = 14;

	int result = changeCoins(coins, amount);

	cout << result << endl;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值