最长递增子序列--动态规划

动态规划方法是集合的递推。

1、  最长单调递增子序列 LIS

给定10,4,20,10,15,13 序列(假设从第1项开始)。

确定状态:

以第i项结尾的最长单调递增子序列的长度为f(i)。

初始状态:f(0)=0; //因为没有第0项,因此以第0项结尾的最长递增子序列长度为0;

终止状态:max{f(1),f(2),f(3),…f(n)},其中值最大的就是最长的递增子序列长度;

决策: 已知第i项前的所有f(x),如果ai>ax,那么ai可以放在ax的后面。(要保存所有f(x))

总收益(公式):f(i)=max{f(x)|x<i && ai>ax}+1;  若集合中为空集,则max=0;

复杂度分析:                                                           

   时间复杂度分析:需要遍历i(以第i项结尾的。。。)

                   需要遍历x,找到满足x<i && ai>ax的所有f(x)

                   因此时间复杂度为O(n^2)

    空间复杂度分析:需要保存每个f(i),因此 为O(n)

记录决策:根据问题需要,记录对每个f(i)做出的决策x。

开始代码:

Int  a[]={0,10,4,20,10,15,13};

Int  f[100]={}

int n=sizeof(a)/sizeof(int);

Int max=0;

f(0)=1

bool flag=false;

   for(int i=1;i<=n;i++){

      for(int j=1;j<i;j++){

      if(a[i]>a[j] && f[j]>=max){max=f[j]; flag =true;}

}

if(flag)                             

f[i]=max+1;

else f[i]=max;

//f[i]=max{f[j]| a[i]>a[j]}+1;

}


//最长子序列
//f[i]记录的是以第i个数作为子序列最后一个数的最长递增子序列。(注:第i个数为子序列的最后一个)
//子序列最长的需要从f[i]中遍历得到。
void main(){

	int a[]={0,1,4,2,5,6,9,8,7,12,19,23,89,24,45,48,32};
	int f[100]={0};
	f[0]=1;
	int n=sizeof(a)/sizeof(int);
	 //f[i]=max{f[x]| i>x && a[i]>a[x]}+1;
	for(int i=1;i<n;i++){
		f[i]=1;
		for(int j=0;j<i;j++){
		if(a[i]>a[j] && f[j]>=f[i])
			f[i]=f[j]+1;
		}
	
	}
	int max=0;
	for(int i=0;i<n;i++){
		cout<<' '<<f[i];
		if(f[i]>max)  max=f[i];
	}
	cout<<"\n max="<<max;
	while (true)
	{

	}
}

//最长增长子序列
//f[i]记录的是以原序列中以第i个数结尾的最长递增子序列。(注:第i个数不一定在子序列中)
//因此,最大长度就是f[n-1]所记录的
void main(){
	int a[]={0,1,4,2,5,6,9,8,7,12,19,23,89,24,45,48,32};
	int f[100]={0};
	f[0]=1;
	int max=0;
	int len=sizeof(a)/sizeof(int);
	bool flag=false;
	for(int i=1;i<len;i++){
		for(int j=0;j<i;j++){
		 //f[i]=max{f[x]| i>x && a[i]>a[x]}+1;
			if(a[i]>a[j]&& f[j]>=max){
					max=f[j];	
					flag=true;
			}
			
		}

	 if(flag)		
		f[i]=max+1;
	else f[i]=max;
	flag=false;
	max=f[i];
	}
	int i=0;
	while(i<len){	
	cout<<"  "<<f[i];
	i++;
	}
	cout<<"\n max= "<<f[len-1];
	while (true)
	{

	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值