zoukankan      html  css  js  c++  java
  • 最长递增子序列 (LIS) Longest Increasing Subsequence

    问题描述:

    有一个长为n的数列a0, a1,..., an-1.请求出这个序列中最长的上升子序列。请求出这个序列中最长的上升子序列。

    上升子序列:对于任意i<j都满足ai<aj的子序列.

    限制条件

    i <= n <= 1000

    0 <= ai <= 1000000

    两种定义方式 具体看程序注释

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <algorithm>
     5 #define INF 0x3f3f3f3f
     6 using namespace std;
     7 
     8 int n;
     9 int a[128];
    10 //定义 dp[i] 以a[i]作为最末数字的的最长子序列
    11 //状态转移方程 dp[i] = 1//自己
    12 //                   = max(dp[i], dp[j]+1) //i > j && a[i] > a[j] 将a[i] 添加在a[j]后面
    13 int main()
    14 {
    15     freopen("in.txt", "r", stdin);
    16     scanf("%d", &n);
    17     for (int i = 0; i < n; i++)
    18     {
    19         scanf("%d", &a[i]);
    20     }
    21     int dp[128];
    22     memset(dp, 0, sizeof(dp));
    23     for (int i = 0; i < n; i++)
    24     {
    25         dp[i] = 1;
    26         for (int j = 0; j < i; j++)
    27         {
    28             if (a[j] < a[i]) dp[i] = max(dp[i], dp[j]+1);
    29         }
    30     }
    31     cout << dp[n-1] << endl;
    32     //复杂度 O(n^2)
    33     //---------------------------------------------------------------------------//
    34     //定义dp[i] 长度为i+1 的序列 的最小结尾值 因为结尾值最小 在后面更新时 越有优势
    35     //状态转移方程 dp[i] = min(dp[i], a[j])
    36     fill(dp, dp+128, INF);
    37     for (int j = 0; j < n;j++)//注意是要对每一个数从前往后只检查一次 去看能否替换 dp数列中的某个值
    38     {
    39         for (int i = 0; i < n; i++)
    40         {
    41             if (i == 0 || dp[i-1] < a[j]) dp[i] = min(dp[i], a[j]);//因为是要求递增 那么比前一个大的话更新这一位 使这一位为最小值
    42         }
    43     }//这样实现也是O(n^2)的复杂度
    44     //但是在查找a[j]的过程 可以使用二分查找 优化这样复杂度变为n*logN
    45     int ans = 0;
    46     for (int i = 0; i < n; i++)
    47     {
    48         if (dp[i] < INF) ans = i+1;
    49     }
    50     cout << ans << endl;
    51     //--------------------------------------------------------------------//
    52     fill(dp, dp+128, INF);
    53     for (int i = 0; i < n; i++)
    54     {
    55         *lower_bound(dp, dp+n, a[i]) = a[i];//dp[0] 到 dp[n-1] >= a[i] 的最小指针 也就是按照从左到有的顺序
    56     }
    57     for (int i = 0; i < n; i++)
    58     {
    59         if (dp[i] < INF) ans = i+1;
    60     }
    61     cout << ans << endl;
    62     return 0;
    63 }
  • 相关阅读:
    纪念这一天,我找到了实习工作
    在编程的道路上坚定地走下去
    今天是1024程序员节
    趣谈函数调用与返回值
    为期3个月的实训结束了,有感而发
    学习编程时遇到难点怎么办?
    今天学习了安卓中的UI线程
    Java程序员要掌握的常用快捷键
    我是一个注重基础的人
    我也有自己的小家啦
  • 原文地址:https://www.cnblogs.com/oscar-cnblogs/p/6380202.html
Copyright © 2011-2022 走看看