leetcode 322:零钱兑换

leetcode 322:零钱兑换


无限背包问题
有N种物品和一个容量为V的背包,每种物品都有无限件可用,第i件物品消耗的容量为Ci,价值为Wi,求解放入哪些物品可以使得背包中总价值最大。
无限背包(完全背包)特点:物品种类为n个(每种物品数量无限)
题目描述:给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1

解题步骤:看到这类题目第一想法就是采用贪心算法来求解。但是贪心算法也存在不足之处:
如果我们换一组钞票面值,比如 1, 5, 11,我们要凑出15的时候, 贪心策略就会出错:
15 = 11 * 1 + 1 * 4 (贪心策略)
15 = 5 * 3(正确策略)
由于贪心算法无法适用于所有面额的情况,我们采用动态规划的方法来求解
1、 状态定义:dp[i]表示凑出金额i所需要的最小硬币数量
2、 状态转移方程:dp[i] = min(dp[i],dp[i-coins[i]]+1) (i >= conins[i])
Conins[i]表示最后一枚硬币的面值数,将该硬币添加进去后,总金额数减少,并且硬币数量增加
3、 初始化:dp[0] = 0,其他dp[i] = amount+1;
4、 输出:dp[amount]
代码

    public int coinChange(int[] coins, int amount) {
        int[] dp = new int[amount+1];
        Arrays.fill(dp, amount+1);
        dp[0] = 0;
        for (int i = 1; i < dp.length; i++) {
        	for(int j = 0;j < coins.length;j++) {
            	if(i >= coins[j])
            		dp[i] = Math.min(dp[i], dp[i-coins[j]]+1);
        	}
		}
        System.out.println(Arrays.toString(dp));
        if(dp[amount] > amount)
            return -1;
        return dp[amount];
    }
发布了28 篇原创文章 · 获赞 0 · 访问量 258

猜你喜欢

转载自blog.csdn.net/zy450271923/article/details/105300890
今日推荐