美文网首页
零钱兑换

零钱兑换

作者: 最困惑的时候就是能成长的时候 | 来源:发表于2019-05-21 16:43 被阅读0次

题目地址:https://leetcode-cn.com/problems/coin-change/
题解:

一.思考步骤

1.建模

①解:<x1,x2...xn>代表了Xi代表了第i种硬币的个数
②目标函数:所有金币的价值为总数accout,且数量最少min\{\Sigma_{i=1}^nx_i \}
③约束条件:所有的金币价值为accoutaccount = \Sigma_{i=1}^nv_ix_i

2.子问题优化

我使用k种硬币,总数为y,那么k=n,y=account的时候是原问题,F_k(y)代表了k种硬币,组成y总数时的最小硬币 数
⑴:y>Vk,y>0,k>0

F_k(y) = min\{F_{k-1}(y),F_k(y-v_k)+1\}
⑵:y=0或者k=0
F_k(y) =0
⑶:y<Vk
F_k(y) =F_{k-1}(y)
⑷:y<Vk,且k=1
F_k(y) =-1

3.归结公式

F_k(y) \begin{cases} min\{F_{k-1}(y),F_k(y-v_k)+1\}, &当y>vk,k>0,y>0;\\ 0, &当y=0;\\ F_{k-1}(y),&当y<w_k;\\ ∞,&当k=1,y<w_1或k=0 \end{cases}

二.伪代码

dp[][]=new int[n+1][account+1]; 代表了k种,y总量的最小硬币数
for i=0 →n+1
   dp[i][0]=0;  //条件二
for j=1 →account+1
   dp[0][j]=∞;  //条件四
for i=1 →n+1
   for j=1 →account+1
      分成三种情况:
      1.如果j>coins[i],那么说明当前至少有一个硬币,dp[i][j]=min(dp[i][j-coins[i]]+1,dp[i-1][j]);
      2.如果j=coins[i],那么说明当前刚好够一个硬币dp[i][j]=1
      3.如果j<coins[i],那么说明当前的第i种硬币面值过大,应该减少,但是如果i=1的话说明只用第一种硬币无法满足条件,也就是dp[1][j]=∞,不等于1的话  dp[i][j]=dp[i-1][j]
最后返回dp[n][account]

三.代码

public int coinChange(int[] coins, int amount) {
        int[][] dp=new int[coins.length+1][amount+1];
        for(int i=0;i<coins.length+1;i++)dp[i][0]=0;
        for(int i=0;i<amount+1;i++)dp[0][i]=Integer.MAX_VALUE;
        for(int i=1;i<coins.length+1;i++){
            for(int j=1;j<amount+1;j++){
                //情况一
                if(j>coins[i-1])dp[i][j]=(dp[i][j-coins[i-1]] ==Integer.MAX_VALUE)?dp[i-1][j]:Math.min(dp[i][j-coins[i-1]]+1,dp[i-1][j]);
                //情况二
                else if(j==coins[i-1])dp[i][j]=1;
                //情况三
                else{
                   if(i==1)dp[i][j]=Integer.MAX_VALUE;
                   else dp[i][j]=dp[i-1][j];
                }
            }
        }
        if(dp[coins.length][amount]==Integer.MAX_VALUE) {
            dp[coins.length][amount]=-1;
        }
        return dp[coins.length][amount];
    }

四:其它写法

public int coinChange(int[] coins, int amount) {
        int[] dp=new int[amount+1];
        dp[0]=0;
        for(int i=1;i<amount+1;i++) {
            dp[i]=Integer.MAX_VALUE;
            for(int j=0;j<coins.length;j++) {
                if(i-coins[j]>=0&&dp[i-coins[j]]+1<dp[i]&&dp[i-coins[j]]!=-1) {
                    dp[i]=dp[i-coins[j]]+1;
                }
            }
            if(dp[i]==Integer.MAX_VALUE) {
                dp[i]=-1;
            }
            
        }
        return dp[amount];
    }
这种就是先去计算dp[i]在使用所有硬币的时候的硬币数,然后到dp[amount]的时候比较各个dp[amount-coins[i]]的关系

相关文章

  • LeetCode-322-零钱兑换

    LeetCode-322-零钱兑换 322. 零钱兑换[https://leetcode-cn.com/probl...

  • LeetCode 零钱兑换 背包问题

    题目地址:322.零钱兑换 leetcode地址518.零钱兑换2 leetcode地址类似题目:123.股票问题...

  • 动态规划

    1. 零钱兑换 零钱兑换 (Medium) 力扣 题目描述:给定不同面额的硬币 coins 和一个总金额 amou...

  • 零钱兑换

    给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。...

  • 零钱兑换

    问题描述 给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的...

  • 零钱兑换

    题目描述:给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的...

  • 零钱兑换

    题目来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/coin...

  • 零钱兑换

    题目: 题目的理解: 看似很简单的题目,用了一天时间编写算法,但是结果是一直计算超时,!_!参考了其他的解题思路,...

  • 零钱兑换

    题目地址:https://leetcode-cn.com/problems/coin-change/题解: 一.思...

  • 零钱兑换

网友评论

      本文标题:零钱兑换

      本文链接:https://www.haomeiwen.com/subject/auodzqtx.html