问题描述:
设有n个不相同整数组成的数列,记为:b(1),b(2),...,b(n)且b(i)<>b(j)(i<>j),若存在i1<i2<i3<...<ie且b(i1)<b(i2)<b(i3)<...<b(ie),则称为长度为e的不下降序列,程序要求:原数列出之后,求出最长不下降序列。
例如:13,7,9,16,38,24,37,18,44,19,21,22,63,15.其中13,16,18,19,21,22,63,就是一个长度为7的不下降序列,同时也有7,9,16,18,19,21,22,63组成的长度为8的不下降序列。
输入样例:
14
13 7 9 16 38 24 37 18 44 19 21 22 63 15
输出样例:
max=8
7 9 16 18 19 21 22 63
算法分析:
根据动态规划原理,由后往前进行搜索(当然从前往后也是一样)。
(1)对 b(n)来说,由于它是最后一个数,所以从b(n)开始查找时,只存在长度为一的不下降序列;
(2)若从b(n-1)开始查找,则存在下面两种可能性:
若b(n-1)<b(n),则存在长度为二的不下降序列,b(n-1),b(n);
若b(n-1)>b(n),则存在长度为一的不下降序列,b(n-1)或b(n).
(3)一般若从b(i)开始,此时最长不下降序列应该按下列方法求出:
在b(i+1),b(i+2),...,b(n)中,找出一个比b(i)大的且最长的不下降子序列,作为他的后继。
代码:
#include<bits/stdc++.h>
using namespace std;
int a[10010],b[10010],c[100010];
//a[i]记录原数值
//b[i]表示从i位置到n的最长不下降子序列
//c[i]表示从i位置开始最长不下降序列的下一个位置,若为0,则表示后面没有连接项
using namespace std;
int main()
{
int n,i,j,max,k;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i];
b[i]=1;
c[i]=0;
}
//输入原数列,并给bc赋初值
for(i=n-1;i>=1;i--)//求最长不下降子序列
{
max=0;//i位置之前的最长不下降子序列
k=0;
for(j=i+1;j<=n;j++)
if(a[i]<a[j]&&b[j]>max)
{
max=b[j];
k=j;
}
if(max>0)
{
b[i]=max+1;
c[i]=k;
}
}
k=1;
for(j=1;j<=n;j++)
if(b[j]>b[k])
k=j;//求最长不下降序列的起始位置
cout<<"max="<<b[k]<<endl;
while(k!=0)
{
cout<<a[k]<<' ';
k=c[k];
}
cout<<endl;
return 0;
}