zoukankan      html  css  js  c++  java
  • [acm] 动态规划——最长上升子序列

    最长上升子序列

    子序列简述

    对于数列E = { 3 1 2 1 8 5 6 },{ 1 2 1}是E的子序列,{ 3 2 8 6}也是E的子序列

    E最长上升子序列为 { 1 2 5 6 };

    1

    用dp的思维来解决问题(O( n^2 ))

    dp[i] 存的是在这个数之前的最长字序列(或者最长子序列和,etc),用当前状态与更新状态比较

     dp[i] = max(dp[j] + 1,dp[i]);//这个 + 1就相当于把直接算进去与之前的值比较(可以手动输出下看看差别)
    

    最后的模板

    int a[1005];
    int dp[1005];
    int main()
    {
        int n;
        cin >> n;
        for(int i =0 ; i < n; i++)    cin >> a[i];///输入
        
        int ans = 0;
        dp[0] = 1;//初始化,后面就直接冲i=1开始枚举
        
        for(int i = 1; i < n ; i++){
            for(int j = 0; j < i; j ++){
                if(a[i] > a[j]){
                    dp[i] = max(dp[j] + 1,dp[i]);///之前的状态加上自己(dp[j] + 1)
                                                 ///与上次枚举的状态比较(dp[i])
                }
            }
            
            dp[i] = max(1,dp[i]);//因为j没有枚举i位,所有对于一个数的时候,更新1
            ans = max (ans,dp[i]);
        }
    
        cout << ans << endl;
    }
    

    二分求解( O( nlogn ) )

    这个方法只能求得子序列的长度,无法求和( 因为最后求得的序列不是有效解,但是数目是统一的 )

    对于序列 D = { 3 1 2 5 6 1 2 4 1 8 9 10 11 }
    最后存下来的序列为 { 1 2 4 6 8 9 10 11 }
    但是正确的应该是 { 1 2 5 6 8 9 10 11 }

    核心思想

    if( a[i] 大于 d[所记录的最后一个数] )d[数+1] = a[i]
    else
    替换掉第一个大于或等于他的 d[j] 所在位置的数 (用lower_bound查找)

    最终代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int a[40005];
    int d[40005];
    
    int main()
    {
        int n;
        cin >> n;
        for (int i=1 ; i<=n ; i++) cin >> a[i];
        
        if (n==0)  //0个元素特判一下 
        {
            printf("0
    ");
            return 0;
        }
        
        d[1]=a[1];  ///初始化 
        int len=1;
        
        for (int i = 2 ; i <= n ; i++){
            
            //cout << a[i] <<" :" << endl; ///输出来看看如何运行的
            if (a[i] > d[len]) d[++len] = a[i];  ///如果可以接在len后面就接上
            else  ///否则就找一个最该替换的替换掉 
            {
                int j = lower_bound(d+1,d+len+1,a[i])-d;  ///找到第一个大于它的d的下标,
                //cout <<d[j] << " " << a[i] << endl; ///输出来看看如何运行的
    	    d[j] = a[i]; 
            }
        }
        
      //  for(int i = 1; i <= n ; i++){
      //  	cout << d[i] << endl;
      //	} 
        
        cout << len << endl;    
        return 0;
    }
    
    /*
    13
    3 1 2 5 6 1 2 4 1 8 9 10 11
    */
    
  • 相关阅读:
    《Forward团队-爬虫豆瓣top250项目-开发文档》
    结对-网页贪吃蛇游戏-项目总结
    Forward团队-爬虫豆瓣top250项目-模块测试过程
    Forward团队-爬虫豆瓣top250项目-模块开发过程
    Forward团队-爬虫豆瓣top250项目-项目总结
    《软件工程课程总结》
    课后作业-阅读任务-阅读提问-4
    《20171201-构建之法:现代软件工程-阅读笔记》
    Forward团队-爬虫豆瓣top250项目-最终程序
    课后作业-阅读任务-阅读提问-3
  • 原文地址:https://www.cnblogs.com/hoppz/p/14106461.html
Copyright © 2011-2022 走看看