本题是求一个序列的最长递增子序列,采用动态规划,递推公式为:
f(j) = max{ f(i)+1} ,其中1<=i,并且a(j)>a(i)
其中f(j)表示选择上a(j)时,串长为j的最长递增子序列。注意不是单纯的串长为j的最长递增子序列。
值得注意的是:
1.f(j)要初始化为1,因为单个字符的最长递增子序列的长就是他自己,长度为1。
2.在每次求max{f(i)+1},不能写成f(j)=max(f(j-1),max(f(i)+1,f(j)),因为存在这样的序列,比如{1 7 3 5 9 4 8},如果每次取当前值与前一个值得最大值时,考虑f(6)=f(5)=4,在计算f(7)时,发现a(7)>a(6),于是f(7)=f(6)+1=5,计算结果错误。这里再次强调,f(j)表示的是选上串字符j时的最长递增子序列,所以f(6)=3。也因为如此,在输出结果的时候需要求说有f数组中的最大值。
/*
* f(j)=max{f(i)+1},1<=i<j&&a[i]<a[j]
*/
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
vector<int> a(n+1);
for(int i=1;i<=n;i++)cin>>a[i];
vector<int> f(n+1,1);//一定初始化为1
for(int j=1;j<=n;j++)
for(int i=1;i<j;i++)
if(a[j]>a[i])f[j]=max(f[j],f[i]+1);
int maxl=f[n];
for(int i=1;i<=n;i++) maxl=max(maxl,f[i]);
cout<<maxl<<endl;
}
return 0;
}
这段有效长度不足20行的代码,而且是做过的练习,我在考试中作了整整3个小时!!!最后发现原因就是没有把初值设为1,所以一定要把整个过程理解清楚,不要囫囵吞枣,也不要在同一个地方摔倒了。