zoukankan      html  css  js  c++  java
  • 百练 2757 最长上升子序列

    果然,动态规划的无后效性是和阶段的划分有关的。

    受前面的影响,涉及到n个元素的这种题目,我第一想法就是找前k个元素的最优解。

    但课件里面说了,这是不满足无后效性的:

    “求序列的前n个元素的最长上升子序列的长度”是个
    子问题,但这样分解子问题,不具有“无后效性”
    假设F(n) = x,但可能有多个序列满足F(n) = x。有的
    序列的最后一个元素比 an+1小,则加上an+1就能形成更长上
    升子序列;有的序列最后一个元素不比an+1小……以后的事
    情受如何达到状态n的影响,不符合“无后效性”

    确定了阶段的划分,状态转移方程还是很好理解的,代码也十分容易实现。

    描述

    一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1a2, ..., aN),我们可以得到一些上升的子序列(ai1ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).

    你的任务,就是对于给定的序列,求出最长上升子序列的长度。

    输入

    输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000。

    输出

    最长上升子序列的长度。

     两种代码实现,“人人为我,我为人人”,这八个字还是很形象的。

    人人为我:

    状态i的值Fi由若干个值已知的状态值Fk,Fm,..Fy推出,如求和,取最大值……

     1 //#define LOCAL
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 const int maxn = 1010;
     9 int dp[maxn];
    10 int a[maxn];
    11 
    12 int main(void)
    13 {
    14     #ifdef LOCAL
    15         freopen("2757in.txt", "r", stdin);
    16     #endif
    17 
    18     int i, n, j;
    19     memset(dp, 0, sizeof(dp));
    20     dp[1] = 1;
    21     cin >> n;
    22     
    23     for(i = 1; i <= n; ++i)
    24     {
    25         scanf("%d", &a[i]);
    26         dp[i] = 1;    
    27     }
    28 
    29     for(i = 2; i <= n; ++i)
    30         for(j = 1; j < i; ++j)
    31         {
    32             if(a[j] < a[i])
    33             {
    34                 dp[i] = max(dp[i], dp[j]+1);
    35             }
    36         }
    37 
    38     int ans = 0;
    39     for(i = 1; i <= n; ++i)
    40         ans = max(ans, dp[i]);
    41     printf("%d
    ", ans);
    42     
    43     return 0;
    44 }
    代码君

    我为人人:

    状态i的值Fi在被更新(不一定是最终求出)的时候,依据Fi去更新(不一定是最终求出)和状态i相关的其他一些状态的值Fk,Fm,..Fy

     1 //#define LOCAL
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 const int maxn = 1010;
     9 int dp[maxn];
    10 int a[maxn];
    11 
    12 int main(void)
    13 {
    14     #ifdef LOCAL
    15         freopen("2757in.txt", "r", stdin);
    16     #endif
    17 
    18     int i, j, n;
    19     scanf("%d", &n);
    20     for(i = 1; i <= n; ++i)
    21     {
    22         scanf("%d", &a[i]);
    23         dp[i] = 1;
    24     }
    25 
    26     for(i = 1; i < n; ++i)
    27         for(j = i+1; j <= n; ++j)
    28         {
    29             if(a[j] > a[i])
    30             {
    31                 dp[j] = max(dp[j], dp[i]+1);
    32             }
    33         }
    34 
    35     int ans = dp[1];
    36     for(i = 1; i <= n; ++i)
    37         ans = max(ans, dp[i]);
    38     printf("%d
    ", ans);
    39 
    40     return 0;
    41 }
    代码君
  • 相关阅读:
    Educational Codeforces Round 10 C. Foe Pairs 水题
    Educational Codeforces Round 10 B. z-sort 构造
    CDOJ 1048 Bob's vector 三分
    Educational Codeforces Round 10 A. Gabriel and Caterpillar 模拟
    第14届电子科大初赛民间盗版部分题目题解
    HDU 5654 xiaoxin and his watermelon candy 离线树状数组 区间不同数的个数
    HDU 5653 Bomber Man wants to bomb an Array. dp
    HDU 5652 India and China Origins 二分+并查集
    HDU 5651 xiaoxin juju needs help 数学
    HDU 5650 so easy 数学
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/3851568.html
Copyright © 2011-2022 走看看