动态规划小总结

记录一下最近复习动态规划的心得。

动态规划的核心在于找到状态转移方程。因为动态规划的思想就是当前状态来源于上一刻的状态。

关于确定状态转移方程: 以基本的卖出股票最佳时机为例:

1.首先要确定方程中dp数组的定义和下标,也就是状态的具体含义(股票问题中表示当前资金)。

2.确定状态转移方程:

        第i天的状态有两种: 持股 or 不持股。

        如果持股: 因为今天(i天)买了股票,或者因为昨天(i-1)天就已经持有了股票,今日无操作

        若不持股 可能是因为今天(i天)卖出了股票,或者昨天就没有股票,今日无操作。

3.初始化数组。比如第一天的时候的情况,往往需要特殊处理。

4.遍历顺序,在背包问题中具体就是物品和背包的顺序。

凑硬币例题为例:

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

题解:

public int coinChange(int[] coins, int amount) {
    	if(coins.length == 0)
            return -1;
        int max= amount+1;
        
        int[] dp = new int[max];

        //所有位置设置最大值
        Arrays.fill(dp,max);
        dp[0] = 0; //初始状态
       
        for(int i = 1;i<max;i++){       //外层循环 遍历所有价格 即从0掉amount 每次加1块钱
            for(int j=0;j<coins.length;j++){ //内层循环 遍历所有硬币面值 即遍历数组里每个面值的硬币种类
            
            if(coins[j]<=i){ //如果第j个硬币的价值大于i 就不考虑了 此时对应的硬币个数是dp[i] =amount+1
                
                dp[i] = Math.min(dp[i],dp[i-coins[j]]+1);
                //              不取第j个面值的硬币       取第j个面值的硬币
                //dp[i] 是i块钱时 需要硬币的个数
            }
            }
        }
        if(dp[amount]<=amount){
            return dp[amount];
         
        }else{
            return -1;
        }
        }

1.确定dp数组: dp[i] 表示 金额为i时,需要的硬币个数为dp[i]。

2.确定dp数组:dp[i] = Math.min(dp[i] , d[i-coins[j]]+1) 其 意义为:如果取面值为coins[j]的硬币,总金额会变成 i - coins[j] 硬币个数会+1。不取则情况不变。

3.初始化数组,硬币问题中的数组初始化比较特别,我们需要遍历从0块钱到目标金额(参数amount)的所有情况。所以我们需要一个长度为amount+1 的数组。

同时,利用Arrays.fill()方法将数组每个位置元素设为amount+1 方便后面比较。

dp[0] = 0 因为0块钱不需硬币。至此 初始化数组完成。

4.遍历顺序:有两个需要遍历的数组,一个是表示价格的dp数组,从0块钱到amount,是题解中的外层。第二个是不硬币数组,每个元素都是不同面值的硬币,是题解中的内层。在内层遍历中还要加上遍历条件(coins[j]<=i) 即当硬币面值小于等于当前金额时,才会继续下去,否则dp数组对应位置不会改变,仍为最大值amount+1。

最后的判断:dp[amount]>amount

如果为真 说明此时dp[amount] = amount+1,结合遍历顺序,说明 amount金额无法达到,返回-1

如果为假,说明此时金额可以达到,返回dp[amount]。

未完待续

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值