百练 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。

输出

最长上升子序列的长度。

 

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

人人为我:

百练 2757 最长上升子序列

状态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\n", ans);

42     

43     return 0;

44 }
代码君

我为人人:

百练 2757 最长上升子序列

状态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\n", ans);

39 

40     return 0;

41 }
代码君

你可能感兴趣的:(序列)