动规 最长不下降

Longest Ordered Subsequence

Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 18   Accepted Submission(s) : 4
Problem Description
A numeric sequence of  ai is ordered if  a1 <  a2 < ... <  aN. Let the subsequence of the given numeric sequence ( a1a2, ...,  aN) be any sequence ( ai1ai2, ...,  aiK), where 1 <=  i1 <  i2 < ... <  iK <=  N. For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, e. g., (1, 7), (3, 4, 8) and many others. All longest ordered subsequences are of length 4, e. g., (1, 3, 5, 8).

Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.
 

Input
The first line of input file contains the length of sequence N. The second line contains the elements of sequence - N integers in the range from 0 to 10000 each, separated by spaces. 1 <= N <= 1000
 

Output
Output file must contain a single integer - the length of the longest ordered subsequence of the given sequence.
 

Sample Input
  
  
7 1 7 3 5 9 4 8
 

Sample Output
  
  
4
 


解题思路:如何把这个问题分解成子问题呢?经过分析,发现 “求以ak(k=1, 2, 3…N)为终点的最长上升子序列的长度”是个好的子问题――这里把一个上升子序列中最右边的那个数,称为该子序列的“终点”。虽然这个子问题和原问题形式上并不完全一样,但是只要这N 个子问题都解决了,那么这N 个子问题的解中,最大的那个就是整个问题的解。由上所述的子问题只和一个变量相关,就是数字的位置。因此序列中数的位置k 就是“状态”,而状态 k 对应的“值”,就是以ak 做为“终点”的最长上升子序列的长度。这个问题的状态一共有N 个。状态定义出来后,转移方程就不难想了。假定MaxLen (k)表示以ak 做为“终点”的最长上升子序列的长度,那么:
MaxLen (1) = 1

MaxLen (k) = Max { MaxLen (i):1<i < k 且 ai < ak 且 k≠1 } + 1
这个状态转移方程的意思就是,MaxLen(k)的值,就是在ak 左边,“终点”数值小于ak,且长度最大的那个上升子序列的长度再加1。因为ak 左边任何“终点”小于ak 的子序列,加上ak 后就能形成一个更长的上升子序列。



#include<iostream>
	using namespace std;
int main()
{
	int n;
	while(cin>>n)
	{
		int i,j,a[1000],d[1000]={0},max=0;
		for(i=1;i<=n;++i)
			cin>>a[i];
		for(i=1;i<=n;++i)
		{
			d[i]=1;
			for(j=1;j<=i-1;++j)
			{
				if(a[j]<a[i]&&d[j]+1>d[i])
					d[i]=d[j]+1;
			}
			if(d[i]>max)
				max=d[i];
		}
		cout<<max<<endl;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值