动态规划之《寻找最大上升序列》

今天做爱奇艺的在线笔试时看到这道题目,这个问题本身见过的,但是当时因为一点小疏忽,导致没有做出来。非常可惜。

问题描述:给出一个序列a1,a2,a3,a4,a5,a6,a7….an,求它的一个子序列(设为s1,s2,…sn),使得这个子序列满足这样的性质,s1< s2< s3< …< sn并且这个子序列的长度最长。找出这个最长序列。(为了简化该类问题,我们将诸如最长下降子序列及最长不上升子序列等问题都看成同一个问题,其实仔细思考就会发现,这其实只是<符号定义上的问题,并不影响问题的实质)
例如有一个序列:1 7 3 5 9 4 8,它的最长上升子序列就是 1 3 4 8 长度为4.

这是一个典型的动态规划问题,动态规划的本质是什么,就是问题阶段的划分和递归公式!

问题阶段的划分
所以我们来重新定义这个问题:
给定一个数列,长度为N,
设Fk为:以数列中第k项结尾的最长递增子序列的长度.
求F1..FN 中的最大值.

很容易发现现在这个问题已经是一个N阶段的问题了。

递推公式
Fk的值应该这样得到,寻找出max{Fi+1} (ai< aj)。

那么我们的思路就应该已经很清晰了。

     #include<vector>                                                                                                                                                                 
  2 #include<iostream>
  3 #include<stdio.h>
  4 
  5 #define maxsize 1000
  6 using namespace std;
  7 #include<algorithm>
  8 vector<int> LIS(vector<int> input){
  9     int d[maxsize];
 10     int p[maxsize];
 11     for(int i=0;i<input.size();i++){
 12         d[i]=1;
 13         p[i]=i;
 14         for(int j=0;j<i;j++){
 15             if(input[i]>input[j]&&d[i]<=d[j]){
 16                 d[i]=d[j]+1;
 17                 p[i]=j;
 18             }
 19 
 20         }
 21 
 22     }
 23     //find the max_index
 24     int max=-INT_MAX;
 25     int max_index=0;
 26     for(int i=0;i<input.size();i++){
 27         if(d[i]>max){
 28             max=d[i];
 29             max_index=i;
 30         }
 31 
 32     }
 33     //find the path by p
 34     int fa;
 35     vector<int> ans;
 36     for(fa=max_index;fa!=p[fa];fa=p[fa]){
 37         ans.push_back(input[fa]);
 38     }
 39     ans.push_back(input[fa]);
 40     reverse(ans.begin(),ans.end());
 41     return ans;
 42 }
int main(){
 45     vector<int> input;
 46     input.push_back(5);                                                                                                                                                          
 47     input.push_back(56);
 48     input.push_back(59);
 49     input.push_back(7);
 50     input.push_back(71);
 51    vector<int> ans=LIS(input);
 52    for(auto item:ans)
 53        cout<<item<<endl;
 54    return 0;
 55 
 56 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值