最长单调递增子序列问题(动态规划)
Posted 三剑客J
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长单调递增子序列问题(动态规划)相关的知识,希望对你有一定的参考价值。
问题
给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4.
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using std::cout;
//L,输入序列
//LIS,最长递增子序列通过LIS返回
//num,序列长度
int Longest_Increament_Subsequence(int *L, int *LIS, int num)
{
int *longest = new int[num];//记录结点最长子序列长度
int *sq = new int[num];//记录该结点所在序列中以该结点为结束结点的序列的长度
int *path = new int[num];//记录该结点的上一个结点
int *endpoint = new int[num];//记录当前序列,最长子序列的终点位置
//初始化,
for (int i = 0; i < num; i++)
{
sq[i] = 1;
longest[i] = 1;
path[i] = i;
endpoint[i] = i;
}
//从第二个结点开始,依次记录包括该结点在内的之前所有结点,分别以每个结点为终点的最长递增子序列,
//即第i个结点就分为i个子问题,而最长递增子序列就是所有子问题中最长的那个。
for (int i = 1; i < num; i++)
{
for (int j = 0; j < i; j++)//更新数组sq的值,
{
if (L[i]>L[j] && sq[i] <= sq[j])
{
sq[i] = sq[j] + 1;//更新以i结点为终点的最长递增子序列的长度,选出最大的值
path[i] = j;//记录下该结点的上一结点
}
}
//判断i结点为当前序列的单调递增子序列的最后结点,该子序列是否是当前序列的最长递增子序列
if (sq[i] <= longest[i - 1])//不是,即该结点添加进来,不没有让最长子序列+1
{
longest[i] = longest[i - 1]; //最长递增子序列仍和没加该结点之前一样
endpoint[i] = endpoint[i - 1];//终点位置也和没加一样
}
else //是,即该结点添加进来,让最长子序列+1
{
longest[i] = sq[i]; //最长递增子序列加一
endpoint[i] = endpoint[i];//终点位置为该结点
}
}
//根据 path数组 输出最长递增子序列
for (int i = endpoint[num-1], j = longest[num - 1] - 1; j >= 0;j--)
{
LIS[j] = L[i];
i = path[i];
}
return longest[num-1];//最长递增子序列的长度返回
}
void main()
{
//举例
int L[] = { 7, 6, 8, 3, 2 }; int num = 5;
int LIS[5]; int Long;
//调用函数
Long=Longest_Increament_Subsequence(L, LIS, num);
//输出最长递增子序列
for (int i = 0; i < Long; i++)
{
cout << LIS[i] << " ";
}
cout << "\n";
}
以上是关于最长单调递增子序列问题(动态规划)的主要内容,如果未能解决你的问题,请参考以下文章