浅显易懂的DP最长递增子序列

原文思路来自知乎,刚学DP的小白按照作者的思路打了一份代码,见:
动态规划的本质

我们先从一个情景开始:

假设小明有n本书放在一个大柜子里,每本书上都有编号,称为书籍编号,而它的放置顺序为顺序编号。

有一天妈妈看到小明书柜里的书书籍编号都是乱的,让他将编号按从大到小的顺序整理好。

但是小明想偷个懒,他想只整理一次,就将最多的书籍整理出来。

于是小明拿来另一个小柜子,目的是从大柜子里的书按照他们的顺序编号一本一本拿出来,使他们的书籍编号按递增顺序。设其中i为前几次把书抽出来, j为小柜子放进了多少本书,1<=j<=i,而f[i][j]记录前i次的最后一本书最小的书籍编号。能放的书不能超过小明拿的次数,因为每次只能抽出一本,拿出来的书可以放回,但后一次拿出来的书不能放到前一次拿出的书的前面。

小明最多能整理出多少书呢?

举个栗子

i 1 2 3 4 5 6
a[i] 1 7 2 8 3 4

可以看到第一本书的书籍编号是1,第二本书的书籍编号是7…

小明心想,不管三七二十一,先将第一本书放进小柜子再说。

于是 f[1][1] = a[1],代表第一次拿出了第一本书的编号,也就是将a[1]记录下来

在第二次拿书的时候,如果第二本书的书籍编号比f[1][1]小,那放进小柜子是不可能比完成递增的条件
那么f[2][1] = f[1][1] 表示前两次都只拿出了第一本书

很幸运,第二本书的编号是7,比a[1]大,于是小明高兴地把第二本书放进了柜子
并记录了 f[2][2]=a[2],表示前二次拿书最后一本为第二本书的书籍编号,聪明的小明还将
f[2][1] = a[1]记录了下来(读者可以思考一下为什么)。

在第三次拿书的时候,第三本书的编号是2,小明想起自己刚刚记录的f[2][1],也就是第一本的书籍编号,第三本可以放到第一本的后面,但它比第三本书的书籍编号7小,那么小明只有两个选择:

1.将第二本书放回大柜子,放进第三本书
2.将第三本书放回大柜子

机智的小明又想到:因为之后要放更多的书,那么放到最后的书籍编号要尽可能小
有:

if (a[i]>f[i-1][k-1]){
   //将a[i]和序列中倒数第二项进行比较 如果比它大 可预选  
			if(a[i]>f[i-1][k]) ++k,f[i][k-1] = f[i-1][k-1],f[i][k] = a[i];
			//如果比倒一大 增加序列的长度 将它放进原先的倒一后面 同时需要将倒二和倒一状态转移 
			else f[i][k-1] = f[i-1][k-1],f[i][k] = a[i];
			//比倒数第一项小 将原先的倒一替换 同时也要记得转移倒二 
		}
		// 将刚输入的数字与前i-1项 k-1长度最后一位的最小值进行比较
		// 将a[i]和原先的最小值进行比较 同时增加序列的长度 
		else f[i
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值