#include<iostream> using namespace std; int minStep,n,*arr,*record,*lis,index,recordMax,lisCount; /* 1.minStep :存放"只"遍历一次指定数组,得到的LIS的长度.比如: *arr={4,5,1,2,3}; 遍历该数组过后,minStep=2,即为{4,5} 两个元素的长度.具体请看getMinStep方法. 2.*arr : 存放输入的,或者随机产生的一组数; 3.*record : 存放遍历过程中符合条件的subsequence. 4.index : record数组的元素个数 5.recordMax : record数组中最大的元素 6.lisCount : LIS个数. 整体思想: 从第一个数开始往后遍历,每遇到一个数,若它大于之前的数, 则它可以要,也可以不要. 若要了,为了不影响之后的判断, 要完之后还得还回来. */ void copy() { for(int i=0;i<lisCount;i++) lis[i]=record[i]; } void dfs(int step) { if(step>=n) { if(index>lisCount) { lisCount=index; copy(); } return; } if(n-step+1<minStep-index) return; else if(recordMax<arr[step+1])//若符合条件,可以放入record { int temp=recordMax;//放入record recordMax=arr[step+1]; record[index]=arr[step+1]; index++; dfs(step+1); index--;//取出,以便递归. record[index]=0; recordMax=temp; } dfs(step+1);//不放入record } int getMinStep()//遍历一次数组,得到一个 IS (不是LIS) 用于剪枝. { int i,count=1,temp=arr[1]; for(i=2;i<=n;i++) if(temp<arr[i]) { temp=arr[i]; count++; } return count; } void init()//initialzation { index=0; recordMax=0; lisCount=0; arr=new int[n+1]; record=new int[n+1](); lis=new int[n+1](); arr[0]=0; for(int i=1;i<=n;i++) cin>>arr[i]; } void show(int max) { cout<<"LIS length: "<<max<<endl; for(int i=0;i<max;i++) cout<<lis[i]<<" "; cout<<endl; } void deleteArray() { delete lis; delete record; delete arr; } int main() { cin>>n; init(); minStep=getMinStep(); if(minStep==n)//整个数组都是递增的,直接输出. { show(n); return 0; } dfs(0); show(lisCount); deleteArray(); return 0; }
时间: 2024-10-09 06:02:36