最长不下降子序列记录路径

例一:求最长上升序列

题目描述
设有由n个不相同的整数组成的数列,记为:b(1)、b(2)、……、b(n)且b(i)<>b(j) (i<>j),若存在i1<i2<i3< … < ie 且有b(i1)<b(i2)< … <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的不下降序列。

输入格式
只有一行,为若干正整数(最多1000个数)

输出格式
为两行,第一行为最上升序列的长度。 第二行为该序列

样例
样例输入
13 7 9 16 38 24 37 18 44 19 21 22 63 15
样例输出
max=8
7 9 16 18 19 21 22 63

两种方法其实也没什么本质上的区别
法一

#include<bits/stdc++.h> 
using namespace std;
int a,count1=0,max1=0,maxi,ans[1005],count2=0;
struct str{
	int b;
	int f;
	int before;
}q[1005];
int main (){
	while(cin>>a){
		q[++count1].b=a;
		q[count1].f=1;//F(i)为b[1.....i]中的最长上升子序列长度(以b[i]为结尾)
	}
	for(int i=2;i<=count1;i++){
		for(int j=1;j<i;j++){
			if(q[i].b>q[j].b&&q[i].f<q[j].f+1){
				q[i].f=q[j].f+1;
				q[i].before=j;//before(j)记录与a[i]相连的上一个下标--记录路径 
			}
		}
		if(q[i].f>max1){
			max1=q[i].f;
			maxi=i;
		}
	}
	cout<<"max="<<max1<<endl;
	for(;maxi>=1;maxi=q[maxi].before){
		ans[++count2]=maxi;
	}
	for(int i=count2;i>=1;i--){
		cout<<q[ans[i]].b<<" ";
	}
	return 0;
}

法二

#include<bits/stdc++.h>
using namespace std;
int n,x,max1,l;
int a[1005],before[1005],dp[1005],ans[1005];
void input(){
	while(cin>>x){
		a[++n]=x;
		dp[n]=1;
	}
	//cout<<"@@@"<<n<<endl;
}
void success(){
	for(int i=2;i<=n;i++){
		for(int j=1;j<i;j++){
			if(a[j]<a[i]&&dp[j]>dp[before[i]]){//j不仅要比i大,盲点:::更要找连接最多的 
				before[i]=j;
				dp[i]=dp[j]+1;
			}
			//else dp[i]=dp[i];
		}
	}
}
void output(){
	max1=0;dp[max1]=0;
	for(int i=1;i<=n;i++){
	//	cout<<dp[i]<<endl;
		if(dp[i]>dp[max1]) 
			max1=i;//寻找最大dp值下标
	}
	cout<<"max="<<dp[max1]<<endl;
	for(;max1>=1;max1=before[max1]){
			ans[++l]=max1;//ans 存下标 
	}
	for(int i=l;i>=1;i--){
		cout<<a[ans[i]]<<" ";
	}
}
int main (){
	input();
	success();
	output();
	return 0;
}
posted @ 2021-12-02 17:55  2T_WANG  阅读(62)  评论(0编辑  收藏  举报