动态规划_基础_最长公共子序列_多种方法_递归/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\n",ans);
40     return 0;
41
42
43
44 }

改了一下,写成动态规划,将原本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\n",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\n",ans);
79     return 0;
80
81
82
83 }

(AC代码)

原文地址:https://www.cnblogs.com/KID-yln/p/12641619.html

时间: 2024-11-10 12:19:44

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

动态规划算法之:最长公共子序列 & 最长公共子串(LCS)

1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. 2.最长公共子串 其实这是一个序贯决策问题,可以用动态规划来求解.我们采用一个二维矩阵来记录中间的结果.这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是"ba"或"ab") b a b c 0 0 0 a 0 1

对最长公共子序列(LCS)等一系列DP问题的研究

LIS问题: 设\(f[i]\)为以\(a[i]\)结尾的最长上升子序列长度,有: \[f[i]=f[j]+1(j<i&&a[j]<a[i])\] 可以用树状数组优化至\(O(nlogn)\) 基于排列的LCS问题(\(a,b\)均为排列,即一个元素不会出现多次): 设\(pos_i\)为\(a_i\)在\(b\)中出现的位置,即\(a_i=b_pos_i\). \(a\)的一个子序列\(a_p_1,a_p_2,...,a_p_m\)是\(a,b\)的公共子序列等价于\(pos

动态规划 - 最长公共子序列(LCS)

最长公共子序列也是动态规划中的一个经典问题. 有两个字符串 S1 和 S2,求一个最长公共子串,即求字符串 S3,它同时为 S1 和 S2 的子串,且要求它的长度最长,并确定这个长度.这个问题被我们称为 最长公共子序列问题. 与求最长递增子序列一样,我们首先将原问题分割成一些子问题,我们用 dp[i][j]表示 S1 中前 i 个字符与 S2 中前 j 个字符分别组成的两个前缀字符串的最 长公共子串长度. 显然的,当 i. j 较小时我们可以直接得出答案,如 dp[0][j]必 等于 0.那么,

最长公共子序列python实现

最长公共子序列是动态规划基本题目,下面按照动态规划基本步骤解出来. 1.找出最优解的性质,并刻划其结构特征 序列a共有m个元素,序列b共有n个元素,如果a[m-1]==b[n-1],那么a[:m]和b[:n]的最长公共子序列长度就是a[:m-1]和b[:n-1]的最长公共子序列长度+1:如果a[m-1]!=b[n-1],那么a[:m]和b[:n]的最长公共子序列长度就是MAX(a[:m-1]和b[:n]的最长公共子序列长度,a[:m]和b[:n-1]的最长公共子序列长度). 2.递归定义最优值

一天一道算法题(4)---最长公共子序列

题目 给定两个字符串str1和str2,返回两个字符串的最长公共子序列 解析 本题是非常经典的动态规划问题,先来介绍求解动态规划表的过程.如果str1的长度为M,str2的长度为N,生成大小为M*N的矩阵dp,行数为M,列数为N.dp[i][j]的含义是str1[0..i]和str2[0..j]的最长公共子序列的长度.从左到右,再从上到下计算矩阵dp. 1.矩阵dp第一列即dp[0..M-1][0],dp[i][0]的含义是str1[0..i]与str2[0]的最长公共子序列的长度. 2.矩阵d

HDU 1159 Common Subsequence --- DP入门之最长公共子序列

题目链接 基础的最长公共子序列 #include <bits/stdc++.h> using namespace std; const int maxn=1e3+5; char c[maxn],d[maxn]; int dp[maxn][maxn]; int main() { while(scanf("%s%s",c,d)!=EOF) { memset(dp,0,sizeof(dp)); int n=strlen(c); int m=strlen(d); for(int i

LCS求最长公共子序列(DP)

动态规划并不是一种算法,而是一种解决问题的思路.典型的动态规划问题,如最长公共子序列(LCS),最长单调子序列(LIS)等. 动态规划分为四个步骤: 1.判断问题是否具有最优子结构 这里以LCS为例,X={x1,x2,...,xi}:Y={y1,y2,...,yj}.最长公共子序列Z={z1,z2,...,zk}: ①如果xi=yj,那么zk=xi=yj,且Zk-1是序列Xi-1和Yj-1的LCS: ②如果xi≠yj,那么zk≠xi:且Zk是序列Xi-1和Yj的LCS: ③如果xi≠yj,那么z

51nod 1006 最长公共子序列Lcs(dp+string,无标记数组实现)

1006 最长公共子序列Lcs 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 取消关注 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列. Input 第1行:字符串A 第2行:字符串B (A,B的长度 <= 1000) Output 输出最长的子序列,如果有多个,随意输出1个. Input示

LCS 最长公共子序列(DP经典问题)

最长公共子序列问题以及背包问题都是DP(动态规划)算法的经典题目,值得深度挖掘以致了解DP算法思想.问题如下: 最长公共子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列. tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最

Longest Common Substring(最长公共子序列)

Longest Common Substring Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 37 Accepted Submission(s): 28   Problem Description Given two strings, you have to tell the length of the Longest Common Su