当前位置:   article > 正文

DP--线性DP--【整理】【经典入门例题】_线性dp题单

线性dp题单

每种类型仅有一个经典的例题,复习一下之前的知识,在学习新知识,不过会推荐一些博客,虽然我也没看过,只是挑一个经典题看看。

1.最长上升子序列(LIS问题)                                                              大佬博客: 最长上升子序列题目大合集

问题描述:给定一个长度n的数列A,求单调递增的子序列的长度最长是多少。

经典基础题:1759:最长上升子序列

描述 一个数的序列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。 输出 最长上升子序列的长度。 样例输入

  1. 7
  2. 1 7 3 5 9 4 8

样例输出

4

a[ i ]表示第i个数,而h[ i ]表示到第i个数时,它是第几个从第“零”个数延伸到的,相当于如下表格

思路:每访问输入的一个数a[i],求往前面找比起小的一个数a[j],则h[i]=h[j]+1.状态转移方程:h[i]=max{h[j]+1},j<i

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int a[108],h[108];
  4. int main()
  5. {
  6. int n;
  7. scanf("%d",&n);
  8. for(int i=1;i<=n;i++)
  9. {
  10. scanf("%d",&a[i]);
  11. h[i]=1;
  12. for(int j=n-1;j>=1;j--)///向前寻找比a[i]小的数
  13. {
  14. if(a[j]<a[i])
  15. {
  16. h[i]=max(h[i],h[j]+1);
  17. }
  18. }
  19. }
  20. int maxx=*max_element(h+1,h+1+n);///求数组里的最大值,最小值同理
  21. printf("%d\n",maxx);
  22. return 0;
  23. }

2.最长公共子序列(LCS)

问题描述:给定两个长度分别为N和M的字符串A和B,求既是A的子序列又是B的子序列的字符串长度最长是多少。

转移方程:f[i,j]=max]\left\{\begin{matrix}f[i-1,j] & & \\ f[i,j-1] & & \\f[i-1,j-1]+1 \end{matrix}\right. if(A[i]==B[j])

边界:f[i,0]=f[0,j]=0     目标:f【N,M】   状态表示:f[i,j]表示前缀子串A【1~i】与B【1~j】的最大公共子序列

经典例题:

例题1:最长公共子序列(POJ1458)大佬博客:动态规划典型例题详解(最长公共子序列(POJ1458), Help Jimmy(POJ1661))
给出两个字符串,求出这样的一 个最长的公共子序列的长度:子序列 中的每个字符都能在两个原串中找到, 而且每个字符的先后顺序和原串中的 先后顺序一致。 
输入 
abcfbc abfcab 
programming contest 
abcd mnp 
输出 


0

大佬思路:

解题思路: 
遇见动归问题,第一步需要考虑状态是什么。 
输入两个串s1,s2 
设MaxLen(i,j)表示:s1的左边i个字符形成的子串,与s2左边的j个 字符形成的子串的最长公共子序列的长度(i,j从0 开始算),则MaxLen(i,j) 就是本题的“状态” 
第二步,就是动用小脑子了,考虑下可能的情况还有递推公式。 
对这道题来说 
MaxLen(n,0) = 0(这里的n是属于s1的) 
MaxLen(0,n) = 0(这里的n是属于s2的)

递推公式: 
if(s1[i - 1] == s2[j - 1]) 
MaxLen(i,j) = MaxLen(i - 1,j - 1) + 1; 
else 
MaxLen(i,j) = Max(MaxLen(i,j - 1),MaxLen(i - 1,j)); 
注:s1[i - 1] != s2[j - 1]时,MaxLen(s1,s2)不会比MaxLen(s1,s2j - 1)和MaxLen(s1i - 1,s2)两者之中任何一个小,也不会比两者都大。

分析:动态规划现在的状态是由前一个状态通过max或min比较得来,由状态表示方程可知 通过枚举一个A【1~i】的元素与另一个串里B【1~j】里的元素比较相同就+,不同就选取最大的

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int maxx[108][108];
  4. int main()
  5. {
  6. string s1,s2;
  7. while(cin>>s1>>s2)
  8. {
  9. int length1=s1.length();
  10. int length2=s2.length();
  11. for(int i = 0 ; i <= length1 ; i++)
  12. maxx[i][0] = 0;
  13. for(int j = 0 ; j <= length2 ; j++)
  14. maxx[0][j] = 0;
  15. for(int i=1;i<=length1;i++)
  16. {
  17. for(int j=1;j<=length2;j++)
  18. {
  19. if(s1[i-1]==s2[j-1])
  20. {
  21. maxx[i][j]=maxx[i-1][j-1]+1;
  22. }
  23. else
  24. maxx[i][j]=max(maxx[i][j-1],maxx[i-1][j]);
  25. }
  26. }
  27. printf("%d\n",maxx[length1][length2]);
  28. }
  29. return 0;
  30. }

3.数字三角形

问题描述:给定一个共有n行的三角形矩阵A,其中第i行有i列。从左上角出发,每次可以向下方或者右下方走一步,最终到达底部。求把经过的所有位置的和加起来,和最大是多少。

状态表示:f【i】【j】表示从左上角走到第i行第j列,和最大是多少。 

阶段划分:路径的结尾位置(矩阵中的行,列位置,即一个二维坐标)

f[i,j]=A[i,j]+max\left\{\begin{matrix} f[i-1,j] \\f[i-1,j-1] if( j>1) \end{matrix}\right.

边界:f[1,1]==A[1,1]  目标:max{f[N,j]}

通过一道例题理解:

描述

如下所示的由正整数数字构成的三角形: 

3 8 
8 1 0 
2 7 4 4 
4 5 2 6 5 

从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,和最大的路径称为最佳路径。你的任务就是求出最佳路径上的数字之和。 
注意:路径上的每一步只能从一个数走到下一层上和它最近的下边(正下方)的数或者右边(右下方)的数。

输入

第一行为三角形高度100>=h>=1,同时也是最底层边的数字的数目。
从第二行开始,每行为三角形相应行的数字,中间用空格分隔。

输出

最佳路径的长度数值。

样例输入

  1. 5
  2. 7
  3. 3 8
  4. 8 1 0
  5. 2 7 4 4
  6. 4 5 2 6 5
  7. 1
  8. 8

样例输出

  1. 30
  2. 8

分析:后一个状态由前面一个状态所确定,令f【】

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/961599
推荐阅读
相关标签
  

闽ICP备14008679号