动态规划--最长单调子序列问题

1.问题描述:

求一个正整数序列的最长单调自增子序列,子序列不要求是连续的。例如

Input:5

5 2 4 3 1

Output:2

2. 算法复杂度是O(N*N)

确定状态转移方程,设f[i]是以a[i]为结尾的最大值的子序列的长度,那么\[\max \{ f[i]\} \]的最大值就是要的结果。

所以转移方程为:

\[f(i) = \max \{ f(x)|x < i,{a_i} > {a_x}\}  + 1\]

所以代码可以为:

void main(void)
{
	int arr[] = {10,4,20,10,15,13};
	int dist[6];
	int path[6];
	int num = 6;
	int i = 0;

	for(i = 0; i < 6; i++)
	{
		dist[i] = 0;
		//-1表示前面没有元素了,用于回头求解的时候定界
		path[i] = -1;
	}

	for(i = 0; i < num; i++)
	{
		int temp = 0;
		int index = -1;

		for(int j = i - 1; j >= 0; j--)
		{
			if(arr[i] > arr[j] && dist[j] > temp)
			{
				temp = dist[j];
				index = j;
			}//if
		}//for

		dist[i] = temp + 1;
		path[i] = index;

	}//for

	//找到最大的那个值
	int max = 0;
	int maxIndex = -1;
	for(int m = 0; m < num; m++)
	{
		if(dist[m] > max)
		{
			max = dist[m];
			maxIndex = m;
		}
	}//for
	printf("最长单曾子序列的长度是%d.\n", max);

	while(path[maxIndex] != -1)
	{
		printf("%d->", arr[maxIndex]);
		maxIndex = path[maxIndex];
	}//while
	printf("%d\n", arr[maxIndex]);

}

  

时间: 2024-10-11 12:17:22

动态规划--最长单调子序列问题的相关文章

最长单调子序列求解

 本篇博文为追忆曾经写过的算法系列第三篇 温故知新 题目重述 已知一个序列,由随机数构成,求其最长单调子序列. 要求:单调分严格和不严格两种情况,并分别求解并输出一个最长单调子序列和所有符合要求的子序列. 问题分析 本题是求解有约束条件的子序列问题,可用动态规划求解.由于本题是求解最长单调子序列的,包括求一个最长单调子序列和求解所有符合要求的序列,下面将按照这两种情况讨论算法复杂度. 求解一个最长单调子序列的算法复杂度 本题假设单调为递增的情况,序列长度为N(任意大小),即序列S[N].若采

动态规划5-最长单增子序列

(LIS Longest Increasing Subsequence)给定一个数列,从中删掉任意若干项剩余的序列叫做它的一个子序列,求它的最长的子序列,满足子序列中的元素是单调递增的. 例如给定序列{1,6,3,5,4},答案是3,因为{1,3,4}和{1,5,4}就是长度最长的两个单增子序列. 处看此题,怎么做? 万能的枚举?枚举全部2^n个子序列,找出最长的,固然可以,就是复杂度太高.我们为什么要枚举呢?因为要知道取了哪些数,其实我们只需要考虑上一个数和取了几个数就可以了吧?因为单增的意思

uva 11400 - Lighting System Design(动态规划 最长上升子序列问题变型)

本题难处好像是在于 可以把一些灯泡换成电压更高的灯泡以节省电源的钱 ,所以也才有了对最优方案的探求 好的处理方法是按照电压从小到大排序,只能让前面的换成后面的,也就满足了把一些灯泡换成电压更高的灯泡 的要求: 一种电压的灯泡,要么不换,要换则应该全换:换,说明用当前的电源不值:而既然不值则应该全部换掉以避免使用当前电源,不然即增加了灯泡费用又没节省电源费用,亏大了... 状态转移详见代码 #include<cstdio> #include<cstring> #include<

最长单调子序列(O(n^2) 和 O(nlg(n))))

给出一个数n,然后给出n个数,求n个数的最长单调子序列.如: n = 7 7    1     5    2    9    3    6 方法一:DP dp[i] 表示元素值不超过i时的最长单调序列.时间复杂度为O(n^2)则可以这样: #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 100000 int a[N]; int dp[N]; int main() { //freop

动态规划---最长上升子序列问题(O(nlogn),O(n^2))

LIS(Longest Increasing Subsequence)最长上升子序列 或者 最长不下降子序列.很基础的题目,有两种算法,复杂度分别为O(n*logn)和O(n^2) . ********************************************************************************* 先回顾经典的O(n^2)的动态规划算法: 设a[t]表示序列中的第t个数,dp[t]表示从1到t这一段中以t结尾的最长上升子序列的长度,初始时设dp[

动态规划 - 最长上升子序列问题

原文  http://xuanwo.org/2015/07/31/dp-lis/ 主题 动态规划 介绍 最长上升子序列问题,也就是 Longest increasing subsequence ,缩写为LIS .是指在一个序列中求长度最长的一个上升子序列的问题,是动态规划中一个相当经典问题.在这里我们可以看到,这个上升实质上就是一个对 < 进行定义的过程,所以我们求解的其实是一类问题,也就是在给定序列中求解长度最长的符合某一性质的子序列的问题.在下面总结的过程中,我还是以递增为例进行阐述. O(

动态规划——最长公共子序列

最长公共子序列(LCS)是一类典型的动归问题. 问题 给定两个序列(整数序列或者字符串)A和B,序列的子序列定义为从序列中按照索引单调增加的顺序取出若干个元素得到的新的序列,比如从序列A中取出 A[i1], A[i2], ...A[ik],其中0=< i1 <= i2 <= ... ik <= n-1得到的新的序列 A[i1].A[i2]....A[ik]即为A的一个子序列.     两个不同的原序列A和B可能有着相同的子序列,求出A和B的公共子序列的最长长度. 分析     这种

动态规划-最长公共子序列

(1).问题描述:给出2个序列,x是从1到m,y是从1到n,找出x和y的最长公共子序列? x:A B C B D A B y:B D C A B A 则:最长公共子序列长度为4,BDAB BCAB BCBA均为LCS(最长公共子序列): 模型实现图: (2).问题解决 代码实现了最长公共子序列的长度 #include<stdio.h> #define N    10 int LCS(int *a, int count1, int *b, int count2); int LCS(int *a,

动态规划 - 最长公共子序列(LCS)

最长公共子序列也是动态规划中的一个经典问题. 有两个字符串 S1 和 S2,求一个最长公共子串,即求字符串 S3,它同时为 S1 和 S2 的子串,且要求它的长度最长,并确定这个长度.这个问题被我们称为 最长公共子序列问题. 与求最长递增子序列一样,我们首先将原问题分割成一些子问题,我们用 dp[i][j]表示 S1 中前 i 个字符与 S2 中前 j 个字符分别组成的两个前缀字符串的最 长公共子串长度. 显然的,当 i. j 较小时我们可以直接得出答案,如 dp[0][j]必 等于 0.那么,