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;
}