一个数的序列 bi,当 b1 < b2 < … < bS的时候,我们称这个序列是上升的。对于给定的一个序列( a1, a2, …, aN),我们可以得到一些上升的子序列( ai1, ai2, …, aiK),这里1 <= i1 < i2 < … < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).
你的任务,就是对于给定的序列,求出最长上升子序列的长度。
Input
输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000。
Output
最长上升子序列的长度。
Sample Input
7
1 7 3 5 9 4 8
Sample Output
4
思路分析
该问题是典型的动态规划问题,它可以分解为以aK为结尾的数能构成最长上升子序列长度这个类型相同而规模减小的子问题,而aK+1构成的最长上升子序列长度与只有ai(0<=i<=k)该值本身及以aK为结尾的序列能构成最长上升子序列长度有关。与aK怎么构成最长上升子序列无关,即该子问题具有“无后效性”。因为如果以ai结尾的序列中没有比ai小的数那么以它结尾的序列的最长上升子序列只有它本身即长度为1。同理,第一个数所构成的最长上升子序列长度也为1.这样动态规划的初始值就知道了。
代码
#include <iostream>
#include<algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
int num[n+5],result[n+5];
for(int i=0;i<n;i++){
cin>>num[i];
//因为如果找不到数比该数还小,则以该数结尾的最长上升子序列的长度为1
//为了减少后面的判断所以直接初始化为1
result[i]=1;
}
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
//以num[i]结尾的最长上升子序列长度等于
//前面所有比num[i]小的数形成的最长上升子序列长度的最大值加1
if(num[i]>num[j])
result[i]=max(result[i],result[j]+1);
}
}
//找出以每个数结尾的最长上升子序列长度中的最大值,max_element返回的是指针所以要加*
cout<<*max_element(result,result+n)<<endl;
return 0;
}
注意点
- max_element()返回的是指针所以要加*表示取该地址中的值。