最近在做动态规划的专题训练,准备写一个动态规划的专栏,因为题目较多,打算分几篇来写。
对于动态规划的概念网上有很多,个人理解对于动态问题,最重要的是写出状态转移方程,其次是写出边界条件,最后根据状态转移方程和边界条件进行代码编写。需要注意的是,与递归方法相比,动态规划是自底向上的,而递归是自顶向下的。所以对于递归问题,我们首先要写出顶层的递推公式,再写出底层的递推出口;而对于动态规划问题,我们往往需要从底层开始求解,然后逐步推到高层,比如说,从a[0]=0,a[1]=1...推到a[n]=n之类的。在动态规划代码中,最常见到的就是for循环和dp[ ]数组,这是因为在dp问题的求解中,总是需要从当前状态推后一个状态,因此需要一个数组来保存当前状态。话不多说,我们来看一道基础dp算法题。
题1.对于任意数组,求它的最长递增子序列长度。比如数组array={5,2,-8,-6,3,6,9,7,10},它的最长递增子序列为-8,-6,3,6,7,10,长度为6。需要注意的是,这里的最长递增子序列不一定是连续的,而是整个数组中最长的递增子序列。
显然,这道题用dp算法是很容易解出来的。首先我们来看看本题的状态转移方程。设maxCur[i]的值为前i个数字的最长递增子序列长度,则
当maxCur[i-1]<=0时,maxCur[i]=maxCur[i-1];
当maxCur[i-1]>0时,maxCur[i]=maxCur[i-1]+1.
本题没有什么特别的边界条件,根据上述状态转移方程,相应代码如下:
public class DP1 {
/**
* @param wj
*/
//最长递增子序列
public static int func(int[] array){
int length=array.length;
if(length==1) return array[0];
int [] maxCur=new int[length];//保存当前最长递增子序列长度
maxCur[0]=1;//第一个元素默认为1
for(int i=1;i<length;i++){
if(array[i]>array[i-1]){
maxCur[i]=maxCur[i-1]+1;
}else{
maxCur[i]=maxCur[i-1];
}
}
return maxCur[length-1];
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] array={5,2,-8,-6,3,6,9,7,10};
System.out.println(func(array));
}
}
输出结果为6,它的最长递增子序列为-8,-6,3,6,7,10.