动态规划常见题型

动态规划其实就是一种遍历,只不过他是带有记忆的遍历,能够直接将前面遍历过的计算应用到后面的计算。这样就节约了大量的时间。为什么动态规划问题可以使用前面遍历过的计算呢,因为使用动态规划解决的问题具有最优子结构性质,即子问题的局部最优将导致整个问题的全局最优,而且动态规划问题具有无后效性原则,即每个阶段的状态一旦确定,此后过程中的演变将不受此前各状态分配的影响。

使用动态规划解决的问题必须符合最优化原理并且具备无后效性原则才可以。

1. 背包问题

什么是01背包问题,01通常是指有N个物品,物品只有被选中或者不被选中两种状态,物品的属性记作weight[i]。而背包是指容器(背包)的容量为M,如何在背包容量的范围内选择物品的问题使得物品的属性和最大的问题,称为01背包问题。在实际的应用中通常会对01背包问题做包装,使其具有实际意义。但是我们只需要抽取题目中的容器,题目中的物品即可。

首先我们需要确定dp数组以及其的含义,对于01背包问题,因为他有背包容量和物品的选择两个变量,所以我们常规解法是用二维dp[i][j]数组做记录。其中dp[i][j]表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大为多少。

因此对于dp[i][j]我们可以从前一个状态递推过来,如果想要得到dp[i][j]这个状态,可能通过两个状态转换过来这两个状态分别为dp[i-1][j],dp[i-1][j-weight[i]]。dp[i-1][j]代表在前i-1个物品能够选取使得容量为j的最大值,所以此时将不选择第i个物品,dp[i][j]=dp[i-1][j]。dp[i-1][j-weight[i]]代表在前i-1个物品能够选取的使得容量为j-weight[i]的最大值,由他转换到dp[i][j]状态得到的值为dp[i-1][j-weight[i]]+value[i]。判断这两种情况的最大值即为dp[i][j]的值。所以递推公式为 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])。

对于背包的初始化,dp[i][0]表示当背包的容量为0时,如何选择前i个物品使得背包中物品的性能和最大,此时因为背包的容量为0,所以不能再选择物品,因此dp[i][0]=0。dp[0][j]是指当背包容量为j时,如何编号为0的物品使得背包中物品的性能和最大。此时只有两个状态,要嘛选择物品0,要嘛不选择,当j>weight[0]时dp[0][j]=value[0],否则dp[0][j]=0。

当我们确定了动态规划的公式和初始化之后,我们就可以遍历物品变量i和背包容量变量j得到结果。

2. 子序列问题

2.1 不连续子序列问题

对于不要求子序列连续的动态规划问题,我们使用dp[i]作为i之前包括i的最长上升子序列。

动态规划的状态转移方程为if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1),因为这里要求的是不连续子序列,所以这里的j为从0到i+1。

对于dp[i]的初始化,因为每个子序列最低都包含自己,所以初始化dp[i]全为1。

我们采用两种for循环,其中外层循环遍历i,内层循环遍历j即可。

 

2.2 连续子序列问题

对于连续子序列,只需要一重for循环,比较i和i-1的大小即可。dp数组的初始化与不连续子序列问题一样。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值