现在的位置: 首页 > 综合 > 正文

双端LIS问题:从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的。

2015年07月23日 ⁄ 综合 ⁄ 共 978字 ⁄ 字号 评论关闭

从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的。

双端LIS问题(从两端做LIS操作)。我们只要在数组的两端进行一次LIS操作,对应的字串长度分别保存在dp[]和dp2[]中,这样我们只要使得dp[i]+dp2[i]-1最大,这个长度就是满足条件的最长字串。


// DoubleLIS.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "stdio.h"
#define N 10
int dp[N];//表示从A[1]到A[i]中以A[i]结尾的最长上升子序列长度
int dp2[N];//表示从A[1]到A[i]中以A[i]结尾的最长下降子序列长度
int a[N] = {0,2,1,5,3,6,4,8,9,7};

int LIS(int n)  //从左往右最长序列的长度
{
	int ans = 1;
	int i, j;
	dp[1] = 1;
	for (i = 2; i < N; i++)
	{
		int tmp = i;
		int max = 0;
		for (j = 1; j < i; j++)
		{
			//从左向右搜索dp数组,若满足上升序列的条件
			//1.若a[i] > a[j]
			//找到dp数组中最大的值,即A[i]之前最大的值
			//2.若a[i]不满足a[i] > a[j]
			//则dp[i] = 1
			if (a[i] > a[j] && dp[j] > max)
				max = dp[j];
			
		}

		//最大值+1就是dp[i]
		dp[i] = max + 1;

	
	}
	

	dp2[N-1] = 1;
	for (i = N-2; i > 0; i--)
	{
	
		int max = 0;
		for (j = N - 1; j > i; j--)
		{
			//从右向左搜索dp数组,若满足上升序列的条件
			//1.若a[i] > a[j]
			//找到dp数组中最大的值,即A[i]之前最大的值
			//2.若a[i]不满足a[i] > a[j]
			//则dp[i] = 1
			if (a[i] > a[j] && dp2[j] > max)
				max = dp2[j];
			
		}
		
		//最大值+1就是dp2[i]
		dp2[i] = max + 1;
		
	
	}

    
	for (i = 1; i < N; i++)
	{
		
		if (dp[i]+dp2[i] > ans)
			ans = dp[i]+dp2[i] - 1;
	}

	return ans;

}
int main(int argc, char* argv[])
{

	printf("%d\n", LIS(N-1));  //从左往右最长序列的长度
	return 0;
}



抱歉!评论已关闭.