• 动态规划——最长不下降子序列(LIS)


      最长不降子序列是这样一个问题:

      

      下面介绍动态规划的做法。

      令 dp[i] 表示以 A[i] 结尾的最长不下降序列长度。这样对 A[i] 来说就会有两种可能:

      1.  如果存在 A[i] 之前的元素 A[j] (j<i),使得 A[j]≤A[i] 且 dp[j]+1>dp[i],那么就把 A[i] 跟在以 A[j] 结尾的 LIS 后面,形成一条更长的不下降子序列(令 dp[i]=dp[j]+1)。
      2.  如果 A[i] 之前的元素都比 A[i] 大,那么 A[i] 就只好自己形成一条 LIS,但是长度为 1。

      由此可以写出状态转移方程

                dp[i] = max{1, dp[j]+1} (j=1,2,....,i-1&&A[j]<A[i])

      上面的状态转移方程中隐含了边界:dp[i]=1(1≤i≤n)。显然 dp[i] 只与小于 i 的 j 有关,因此只要让 i 从小到大遍历即可求出整个 dp 数组。然后从整个 dp 数组中找出最大的那个就是要寻求的整个序列的 LIS 长度,整体复杂度为 O(n2)。

      代码如下:

     1 /*
     2     最长不下降子序列 
     3 */
     4 
     5 #include <stdio.h>
     6 #include <string.h>
     7 #include <math.h>
     8 #include <stdlib.h>
     9 #include <time.h>
    10 #include <stdbool.h>
    11 
    12 #define maxn 100
    13 int A[maxn], dp[maxn]; 
    14 
    15 int main() {
    16     int n, i, j;
    17     scanf("%d", &n);
    18     for(i=1; i<=n; ++i) {                // 输入序列 
    19         scanf("%d", &A[i]);
    20     } 
    21     int ans = -1;                        // 记录最大的长度 
    22     for(i=1; i<=n; ++i) {
    23         dp[i] = 1;                        // 初始为仅为自己 
    24         for(j=1; j<i; ++j) {
    25             if(A[i] >= A[j] && (dp[j]+1 > dp[i])) {
    26                 dp[i] = dp[j] + 1;        // 状态转移方程 
    27             }
    28         }
    29         if(dp[i] > ans) {
    30             ans = dp[i];                // 保存最大值 
    31         } 
    32     } 
    33     printf("%d
    ", ans);
    34 
    35     return 0;
    36 }

          

  • 相关阅读:
    在WPF中应用弱事件模式
    MSTest DeploymentItemAttribute
    delegate, event
    zookeeper 开机启动197
    centos 7 安装solr7.3.0 配置mysql197
    solr7.4 centos7安装197
    centos 查看mysql数据库命令197
    bootstrapValidator验证197
    idea快捷键197
    sun.misc.Unsafe.park(Native Method)197
  • 原文地址:https://www.cnblogs.com/coderJiebao/p/Algorithmofnotes28.html
Copyright © 2020-2023  润新知