標籤:
#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;}
最長遞增子序列LIS遞迴演算法