最长上升子序列(Longest Increasing Subsequence,LIS)是一个数列中最长的(非)严格上升的子序列, LIS的求解是DP思想的一个经典体现, 这里通过例题来介绍两种复杂度不同的解法和一个标记路径的问题。
一. n ^ 2 解法(双层循环递推关系式)
例:hdu 1160
题意是一只老鼠有体重跟速度两种属性, 每一行会都会输入一只老鼠的体重和速度,同时每只老鼠都在输入时按照顺序有了一个编号, 求一个最长的老鼠序列要求老鼠的体重严格上升而速度严格下降, 并将其按照原来输入顺序的编号输出。
题解:用结构体存下每个老鼠的属性及编号, 将其按体重升序排列, 体重相同按速度降序排列。排序之后在速度序列中求一个lis并且标记路径输出即可。
(1)求解lis:
DP的核心思想是将问题分成若干的最优子问题以及确定子问题无后效性, 简单来说就是把一个大的问题转化成小问题的堆积来计算到大问题。拿本题来说, 假设目标数列的长度是n, 则转化成的子问题就是通过对前n - 1, n - 2, n - 3..... 2, 1位数形成数列lis的求解来最终推出目标序列的lis。通过一个DP数组来存下当前位置的最长上升子序列, 通过一个判断关系可以很轻松的通过双层循环得到最终lis的长度。
实现代码如下:
for(i = 0;i < 10;i++){
dp[i] = 1;//初始化为1
for(j = 0;j < i;j++){
if(s[j] < s[i])
dp[i] = max(dp[i], dp[j] + 1);
}
ans = max(ans, d