动态规划_基础_最长公共子序列_多种方法_递归/dp

Posted kid-yln

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划_基础_最长公共子序列_多种方法_递归/dp相关的知识,希望对你有一定的参考价值。

 

D: 魔法少女资格面试

题目描述

众所周知,魔法少女是一个低危高薪职业。随着近年来报考魔法少女的孩子们越来越多,魔法少女行业已经出现饱和现象!
为了缓和魔法少女界的就业压力,魔法少女考核员丁丁妹决定增加魔法少女资质考核的难度。
然而,即使如此,通过资质考核的魔法少女们数量仍然过多,因此,丁丁妹决心增加一轮面试,从而淘汰掉更多的预备魔法少女。
具体而言,她打算对所有面试者询问这样一个问题:
给两个长度为 n 的全排列,它们的最长公共子序列长度是多少?
不幸的是,由于丁丁妹没有好好上过学,她自己也不知道答案是多少,因此她使用魔法找到了你,希望你来帮她解决这个问题。

输入描述

每个测试点仅有一组数据。
第一行是一个正整数 n ,表示全排列长度。
第二行有 n 个整数,保证是一个 n 的全排列。
第三行有 n 个整数,保证是一个 n 的全排列。
其中,保证 1 ≤ n ≤ 1000 。

输出描述

输出一行一个整数,表示两数组的最长公共子序列长度。

样例输入

5
1 3 2 4 5
5 2 3 1 4

样例输出

2

Hint

如果你愿意思考 1 ≤ n ≤ 1000000 时的解法,那么丁丁妹会很高兴地录取你。

 

题解思路

这道题思路比较明显的,关系式就是:

技术图片

 

也可以从后往前写成

L(i,j)=L(i+1,j+1)取等

L(i,j)=max(L(i,j+1),L(i+1,j))不等

但是这个式子我用递归直接写,就给TE了,如下为代码:

技术图片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <numeric>
 6 using namespace std;
 7 typedef long long ll;
 8 const int M=1e3+10;
 9 int n;
10 int a[M],b[M];
11 int ans=1;
12 
13 int dfs(int x,int y) {
14     int t=0;
15     if(y>n||x>n) {
16         return t;
17     } else if(a[x]==b[y]) {
18         t=1+dfs(x+1,y+1);
19     } else {
20         int t1=dfs(x,y+1);
21         int t2=dfs(x+1,y);
22         t=max(t1,t2);
23     }
24 
25     ans=max(ans,t);
26     return t;
27 
28 }
29 /*
30 6
31 5 3 1 4 2 6
32 1 5 3 2 4 6
33 */
34 int main() {
35     scanf("%d",&n);
36     for(int i=1; i<=n; i++)scanf("%d",&a[i]);
37     for(int i=1; i<=n; i++)scanf("%d",&b[i]);
38     dfs(1,1);
39     printf("%d
",ans);
40     return 0;
41 
42 
43 
44 }
View Code

改了一下,写成动态规划,将原本dfs(i,j)改写成dp【i】【j】存起来

i  ,j,表示当前序列 — a,b,分别在哪个位置,dp【i】【j】表示在这一状态下,a1-- ai 与 b1-- bj,存在最大公共子序列的长度

技术图片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <numeric>
 6 using namespace std;
 7 typedef long long ll;
 8 const int M=1e3+10;
 9 int n;
10 int a[M],b[M];
11 int ans=1;
12 int dp[M][M];
13 /*
14 int dfs1(int x,int y) {
15     int t=0;
16     if(y>n||x>n) {
17         return t;
18     } else if(a[x]==b[y]) {
19         t=1+dfs(x+1,y+1);
20     } else {
21         int t1=dfs(x,y+1);
22         int t2=dfs(x+1,y);
23         t=max(t1,t2);
24     }
25 
26     ans=max(ans,t);
27     return t;
28 
29 }
30 
31 
32 int dfs(int x,int y) {
33     int t=0;
34     if(y<1||x<1) {
35         return t;
36     } else if(a[x]==b[y]) {
37         t=1+dfs(x-1,y-1);
38     } else {
39         int t1=dfs(x,y-1);
40         int t2=dfs(x-1,y);
41         t=max(t1,t2);
42     }
43 
44     ans=max(ans,t);
45     return t;
46 
47 }*/
48 /*
49 6
50 5 3 1 4 2 6
51 1 5 3 2 4 6
52 */
53 void f() {
54     int i,j;
55     memset(dp,0,sizeof(dp));
56 
57     for( i=1; i<=n; i++) {
58         for( j=1; j<=n; j++) {
59             if(a[i]==b[j]) {
60                 dp[i][j]=dp[i-1][j-1]+1;
61             } else {
62                 dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
63             }
64         }
65     }
66     printf("%d
",dp[n][n]);
67 
68 }
69 
70 
71 int main() {
72     scanf("%d",&n);
73     for(int i=1; i<=n; i++)scanf("%d",&a[i]);
74     for(int i=1; i<=n; i++)scanf("%d",&b[i]);
75     f();
76 //    int n1=n;
77     //dfs(n1,n1);
78     //printf("%d
",ans);
79     return 0;
80 
81 
82 
83 }
View Code

(AC代码)

 

 

 

以上是关于动态规划_基础_最长公共子序列_多种方法_递归/dp的主要内容,如果未能解决你的问题,请参考以下文章

最长公共子序列_动态规划

算法导论—最长公共子序列(动态规划)

动态规划法最长公共子序列(LCS)问题

动态规划_公共最长子序列 java

动态规划_线性动态规划,区间动态规划

动态规划|删除最少的元素-最长下降子序列