动态规划(dp)

一、动态规划求解步骤及使用条件

  1. 将原问题分解为子问题
  • 需要将原问题分解为若干个子问题,子问题与原问题形式相同或类似。但规模变小。子问题都解决,原问题解决。
  • 子问题一旦求出就会被保存,所以每个子问题只需要解一次。
  1. 确定状态
  • 将子问题相关的各个变量的一组取值,称之为一个“状态”。一个状态对应于一个或多个字问题,某个状态下的值就是这个状态所对应的子问题的解。
    所有状态的集合构成问题的“状态空间”。状态空间的大小与用动态规划解决问题的时间复杂度直接相关。
  1. 确定初始状态的值
    最小子问题的解,无需计算就可得出,通常是递归的边界条件。
  2. 确定状态转移方程
    如何从一个或多个已知的“状态”的“值”求出另一个状态的值(“人人为我”递推型)。状态转移可以用递推公式表示,也称为状态转移方程。

二、 动态规划适用条件

  1. 问题具有最优子结构性质。如果问题的最优解所包含的子问题也是最优的,称问题具有最优子结构性质。
  2. 无后效性。当前若干个状态值一旦确定,则后过程的演变只和这若干个状态值有关,和之前如何演变到该状态无关。

三、常见子问题分解形式和状态转移形式

  1. 将原问题根据问题规模N进行子分解

典型问题:打家劫舍、 删除并获得点数、爬楼梯、斐波那契问题

打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷			窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 1:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:
输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
 偷窃到的最高金额 = 2 + 9 + 1 = 12 。

子问题:(思路)问题分解将规模N将低,f(n)表示n个房间可获得的最大值。第n个房间有两种情况拿或不拿,对应f(n-1)和f(n-2)两个子问题,取两者最大值。

f(n) = max{ f(n-1) , f(n-2) + money[n] }//状态转移方程
f(0) = 0,f(1) = money[1];//初始状态
//至此我们根据f(0),f(1)+状态转移方程逐步向后推算就可解出f(n)。

  1. 根据原问题位置问题解构成形式分解子问题

典型问题:不同路径、最长回文子串

最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:

输入:s = "abababa"
输出:"abababa"

子问题:这时如果我们参考降低字符串长度N规模来分解子问题就会暴露问题。f(n)与f(k),k<n并无关系f(n)为子回文串则f(k)明显不是。观察abababa,babab,aba,b这些字串,变化发生在两侧这时需要两个变量来记录。用i和j来模拟串长两端变化,f(i,j)表示求字符串i,j之间的回文串,则

dp(i,j) = dp( i+1 , j-1 ) && s[i] == s[j] //状态转移方程
j-1 - (i+1) + 1 < 2,得 j - i < 3 //初始条件,表示子串是单字符一定是回文串

在这里插入图片描述

求解过程类似填写一张二维表格,需要注意的是与寻常遍历i,j不同因为dp[i][j]根据dp[i+1][j-1]推出,即表格左下方元素,如果我们先填第一行、第二行,则在dp[0][3]时dp[1][2]并未计算。故正确的填写顺序为沿对角线从上到下填写。对应的是以2为长度的回文子串、3的回文子串。

Tips:输出结果:我们需要在遍历过程中就记录最长子串长度和起始位置。避免填写表格后再遍历找最长字串,类似在求解过程附带打擂台。

本文旨在提供解题的思路故不放程序源代码,题目皆出自leetcode感兴趣的朋友可以去leetcode查找。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值