当前位置: 代码迷 >> 综合 >> wust oj 1867 (输出最长不下降子序列)【最长序列输出类模板】
  详细解决方案

wust oj 1867 (输出最长不下降子序列)【最长序列输出类模板】

热度:74   发布时间:2023-12-23 00:26:58.0

Description

设有由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的不下降序列。

Input

实现一个整数n,表示整数个数。接着包含n个整数。(不超过1000)

Output

首先输出最长不下降序列的长度,形如“max=长度”。

第二行就是最长不下降序列中的各个整数。如果有多个答案,只输出最前面的序列。

Sample Input 






  7 300 250 275 252 200 138 245

 

Sample Output

max=2

250 275


 【题解】 学到这我想求最长不下降子序列大家应该都会,但是这道题比较特别,许多人都会求其长度,但是会输出这个最长子序列的恐怕不多吧,,这里面还是有一点小技巧的。

 

 首先就是开三个数组,一个存数据,一个标记从每个数据开始到末尾的最长子序列个数,并记录路径,最后一个存它的路径,路径的保存采取并查集的形式,当然并没有用到并查集,不要惊讶,,

 你可以把它想象成指针,前一个指针指向一个元素的地址,而此元素里存的是下一个符合条件的地址,这样就可以每次输出每个地址内的元素内容,达到保存路径的目的。

 

 就像->->->->->...原理一样,希望你能理解。

 【AC代码】

 

#include <iostream>
#include <vector>
using namespace std;int main()
{int tmp,t;while (cin>>t){vector<int> data;//开数组vector<int> max_sub_num;vector<int> ind_nex_num;while(t--){cin>>tmp;data.push_back(tmp);//读入数据max_sub_num.push_back(1);//每个数据刚开始的最长不下降子序列都是1ind_nex_num.push_back(0);//后继都为0}int n = data.size();for(int i=n-1;i>=0;--i)//从都往前遍历{int maxlen = 0;int p=0;for (int j=i+1;j<n;++j)//记录从第i个数到最后一个数之间的最长不下降子序列{if (data[i] < data[j] && max_sub_num[j] > maxlen){maxlen = max_sub_num[j];p = j;}}if (p != 0)//存在此序列{ind_nex_num[i] = p;//记录从i点往后的最长不下降序列长度max_sub_num[i] = max_sub_num[p]+1;//i点起往后的最大不下降序列长度加1}}int maxLen = 0;int p = 0;for (int i=0;i<max_sub_num.size();++i)//遍历所有从i开头的元素,找到最长序列{if (max_sub_num[i] > maxLen){p = i;maxLen = max_sub_num[i];}}cout<<"max="<<maxLen<<endl;//输出序列cout<<data[p];p= ind_nex_num[p];while(p!=0){cout<<" "<<data[p];p = ind_nex_num[p];}cout<<endl;}return 0;
}

  相关解决方案