DP问题
目的:空间换时间,提升效率
方式:找出有规律性的递推公式以及限定条件
n-1
步为整体 + 接下来的后一步】
n-1
步得到的最优结果加上第n步的结果,取最优得到问结果但不是具体内容的,求的是具体一个数,一般用DP比如
问所有种类的结果的内容,一般递归,深度搜索这些。
而,递归做了很多重复计算,因此可以将计算结果保存下来,避免重复计算。
一、确定状态
也就是 f n , f i , j f_n,f_{i,j} fn,fi,j之类的
把问题分割为2部分:
最后一步
子问题
二、转移方程
就是递进的规律方程,把子问题和最后一步的联系规律找到了
比如:
f X = m i n { f X − 2 + 1 , f X − 5 + 1 , f X − 7 + 1 } f_X = min\{f_{X-2}+1, f_{X-5}+1, f_{X-7}+1\} fX=min{fX−2+1,fX−5+1,fX−7+1}
这里表达了 f x f_x fx(最后一步)和 f X − f_{X-} fX−(子问题)的关系
三、初始条件和边界情况
初始条件:
最开始(小范围)的数值,用于初始化,人工设定
(这些初始值用转移方程是算不出来的,然后后面递进计算又要用到的值)
比如:
这个维数和遍历对应,也和需要的变量对应
边界条件:
对于每次迭代计算,都要在合理的边界下计算
比如不存在的情况下,返回null
四、计算顺序
从前往后、从小往大、从大到小等。。。
顺序原则:看计算要依赖的方向,也就是转移方程中,谁靠谁得到后续的结果
问题:在学习视频,1:10:52的地方
思路(按照方法先自己想的):
一、确定状态,分离子问题和最后一步
蛙能否跳到n-1,能否跳到n-2,…,能否跳到1。
二、确定转移方程
f n = ( f 0 + r e s t 0 ) ∣ ∣ ( f 1 + r e s t 1 ) ∣ ∣ . . . ∣ ∣ ( f n − 1 + r e s t n − 1 ) ∣ ∣ ( f n + r e s t n ) f_n = (f_0 + rest_0) || (f_1 + rest_1) || ... || (f_{n-1} + rest_{n-1}) || (f_n + rest_n) fn=(f0+rest0)∣∣(f1+rest1)∣∣...∣∣(fn−1+restn−1)∣∣(fn+restn)
r e s t i rest_i resti表示在石头 n i n_i ni处剩下需要跳的数,跳过了,就 t r u e true true了
有一个 t r u e true true就返回 t r u e true true
三、确定边界和初始值
就n块石头
f 0 = t r u e f_0=true f0=true
四、整体总结
需要一个一维变量boolean [n] re
,记录是否可以跳到对应下标的石头上
所以,数组re
应该初始化为false
,能跳再改为true
五、代码(没验证,凭感觉走的)
public boolean jump(int[] stone){
// stone数组就是题目示例的数组a
//定义数组re存结果
n = stone.length;
int[] re = new int[n];
re[0] = true; //初始化
for(int i = 0; i < n; i++){
//得到在每块石头上的结果
for(int j = 0; j < stone[i]; j++){
if(re[j]){//代表可以跳到这块石头上
re[i+j] = true; //把能跳的地方
}
}
}
return re[n-1];
}