动态规划_基础_最长公共子序列_多种方法_递归/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了,如下为代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <numeric>
using namespace std;
typedef long long ll;
const int M=1e3+;
int n;
int a[M],b[M];
int ans=; int dfs(int x,int y) {
int t=;
if(y>n||x>n) {
return t;
} else if(a[x]==b[y]) {
t=+dfs(x+,y+);
} else {
int t1=dfs(x,y+);
int t2=dfs(x+,y);
t=max(t1,t2);
} ans=max(ans,t);
return t; }
/*
6
5 3 1 4 2 6
1 5 3 2 4 6
*/
int main() {
scanf("%d",&n);
for(int i=; i<=n; i++)scanf("%d",&a[i]);
for(int i=; i<=n; i++)scanf("%d",&b[i]);
dfs(,);
printf("%d\n",ans);
return ; }
改了一下,写成动态规划,将原本dfs(i,j)改写成dp【i】【j】存起来
i ,j,表示当前序列 — a,b,分别在哪个位置,dp【i】【j】表示在这一状态下,a1-- ai 与 b1-- bj,存在最大公共子序列的长度
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <numeric>
using namespace std;
typedef long long ll;
const int M=1e3+;
int n;
int a[M],b[M];
int ans=;
int dp[M][M];
/*
int dfs1(int x,int y) {
int t=0;
if(y>n||x>n) {
return t;
} else if(a[x]==b[y]) {
t=1+dfs(x+1,y+1);
} else {
int t1=dfs(x,y+1);
int t2=dfs(x+1,y);
t=max(t1,t2);
} ans=max(ans,t);
return t; } int dfs(int x,int y) {
int t=0;
if(y<1||x<1) {
return t;
} else if(a[x]==b[y]) {
t=1+dfs(x-1,y-1);
} else {
int t1=dfs(x,y-1);
int t2=dfs(x-1,y);
t=max(t1,t2);
} ans=max(ans,t);
return t; }*/
/*
6
5 3 1 4 2 6
1 5 3 2 4 6
*/
void f() {
int i,j;
memset(dp,,sizeof(dp)); for( i=; i<=n; i++) {
for( j=; j<=n; j++) {
if(a[i]==b[j]) {
dp[i][j]=dp[i-][j-]+;
} else {
dp[i][j]=max(dp[i-][j],dp[i][j-]);
}
}
}
printf("%d\n",dp[n][n]); } int main() {
scanf("%d",&n);
for(int i=; i<=n; i++)scanf("%d",&a[i]);
for(int i=; i<=n; i++)scanf("%d",&b[i]);
f();
// int n1=n;
//dfs(n1,n1);
//printf("%d\n",ans);
return ; }
(AC代码)
动态规划_基础_最长公共子序列_多种方法_递归/dp的更多相关文章
- 动态规划(一)——最长公共子序列和最长公共子串
注: 最长公共子序列采用动态规划解决,由于子问题重叠,故采用数组缓存结果,保存最佳取值方向.输出结果时,则自顶向下建立二叉树,自底向上输出,则这过程中没有分叉路,结果唯一. 最长公共子串采用参考串方式 ...
- 动态规划模板2|LCS最长公共子序列
LCS最长公共子序列 模板代码: #include <iostream> #include <string.h> #include <string> using n ...
- 对最长公共子序列(LCS)等一系列DP问题的研究
LIS问题: 设\(f[i]\)为以\(a[i]\)结尾的最长上升子序列长度,有: \[f[i]=f[j]+1(j<i&&a[j]<a[i])\] 可以用树状数组优化至\( ...
- 动态规划----最长公共子序列(LCS)问题
题目: 求解两个字符串的最长公共子序列.如 AB34C 和 A1BC2 则最长公共子序列为 ABC. 思路分析:可以用dfs深搜,这里使用到了前面没有见到过的双重循环递归.也可以使用动态规划,在建 ...
- 动态规划 - 最长公共子序列(LCS)
最长公共子序列也是动态规划中的一个经典问题. 有两个字符串 S1 和 S2,求一个最长公共子串,即求字符串 S3,它同时为 S1 和 S2 的子串,且要求它的长度最长,并确定这个长度.这个问题被我们称 ...
- 动态规划——最长公共子序列LCS及模板
摘自 https://www.cnblogs.com/hapjin/p/5572483.html 这位大佬写的对理解DP也很有帮助,我就直接摘抄过来了,代码部分来自我做过的题 一,问题描述 给定两个字 ...
- [Python]最长公共子序列 VS 最长公共子串[动态规划]
前言 由于原微软开源的基于古老的perl语言的Rouge依赖环境实在难以搭建,遂跟着Rouge论文的描述自行实现. Rouge存在N.L.S.W.SU等几大子评估指标.在复现Rouge-L的函数时,便 ...
- 最长公共子序列lcs 51nod1006
推荐参考博客:动态规划基础篇之最长公共子序列问题 - CSDN博客 https://blog.csdn.net/lz161530245/article/details/76943991 个人觉得上面 ...
- HDU 1159 Common Subsequence --- DP入门之最长公共子序列
题目链接 基础的最长公共子序列 #include <bits/stdc++.h> using namespace std; ; char c[maxn],d[maxn]; int dp[m ...
- 最长公共子序列python实现
最长公共子序列是动态规划基本题目,以下依照动态规划基本步骤解出来. 1.找出最优解的性质,并刻划其结构特征 序列a共同拥有m个元素,序列b共同拥有n个元素,假设a[m-1]==b[n-1],那么a[: ...
随机推荐
- [剑指offer]25.合并两个排序的链表(迭代+递归)
25.合并两个排序的链表 题目 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的. 示例1: 输入:1->2->4, 1->3->4 输出:1-> ...
- 使用toString()检测对象类型
可以通过toString() 来获取每个对象的类型.为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或 ...
- 【前端词典】这些功能其实不需要 JS,CSS 就能搞定
前言 今天我们大家介绍一些你可能乍一眼以为一定需要 JavaScript 才能完成的功能,其实 CSS 就能完成,甚至更加简单. 内容已经发布在 gitHub 了,欢迎围观 Star,更多文章都在 g ...
- iphone ios app互相调用
正好要做这个,记录一下 1.ios应用程序间互相启动 2.网页如何调用自己的app http://www.dotblogs.com.tw/yang5664/archive/2012/11/24/850 ...
- Python第六章-函数04-递归函数和拉姆达表达式
五.递归函数 什么叫递归(recusive)? 你拿两个镜子互相面对着, 然后去看镜子, 会发现每个镜子中很多个镜子, 层层的嵌套, 无穷尽, 这就是一种递归! 从前有坐山, 山里有座庙, 庙里有个老 ...
- coding++: java把一个整数拆分为单个值
方式一: int num = 100; int[] ary = new int[(num+"").length()]; for(int i = ary.length-1;i> ...
- [POJ2533]Longest Ordered Subsequence<dp>
题目链接:http://poj.org/problem?id=2533 描述: A numeric sequence of ai is ordered if a1 < a2 < ... & ...
- Java面试金典
1,将构造函数声明为私有的作用 构造函数私有化,保证类以外的地方不能直接实例化该类,这种情况下,要创建这个类的实例,只能提供一个公共静态方法,像工厂方法模式,由于构造函数私有化,不能被继承. 2,在t ...
- 记一次Task抛异常,调用线程处理而引发的一些随想
记一次Task抛异常,调用线程处理而引发的一些随想 多线程调用,任务线程抛出异常如何在另一个线程(调用线程)中捕获并进行处理的问题. 1.任务线程在任务线程执行语句上抛出异常. 例如: private ...
- Mybatis中的# 与 $
我们说MyBatis有两种注入参数的方式, - 一种是#{} - 另一种是${} 这两种从使用功能来看差距不大,那为什么会强推使用#? ${}使用的是拼接字符串,#{}使用的是占位符的方法,经过了处理 ...