Codeforces10D–LCIS(区间DP)
题目大意
给定两个序列,要求你求出最长公共上升子序列
题解
LIS和LCS的合体,YY好久没YY出方程,看了网友的题解,主要是参考aikilis的,直接搬过来好了
经典的动态规划优化。
用opt[i][j]表示s[0..i-1]与t[0..j-1]的以t[j-1]结尾的最长上升公共子序列的长度,那么最后的答案是max{opt[n][j] | 1<=j<=m}。
当s[i-1]!=t[j-1]时,由于必须以t[j-1]收尾,所以不可能选择s[i-1],故有:
opt[i][j]=opt[i-1][j]。
当s[i-1]=t[j-1]时,与LIS一样,我们有:
opt[i][j]=1+max{opt[i-1][k] | k<j,t[k]<t[j]}。
如果直接求解这个状态转移方程,时间复杂度是O(n^3),我们需要进行优化,由于主要的时间消耗出现在s[i]=t[j]的情况下,所以我们对这种情况的求解进行优化。
我们按照i优先的顺序求解(外层循环为i),那么注意到在求解opt[i][j]时,主要的工作量是计算max{opt[i-1][k] | k<j,t[k]<t[j]},然而如果我们利用以前已经求解过的opt[][]的值,可以直接得到opt[i][j]=1+max{opt[i-1][k] | k<j,t[k]<t[j]}的值而不用枚举,假设在t[j]之前有一个t[p]满足t[p]=t[j] (p<j),那么我们在求解opt[i][p]的时候已经得到了max{opt[i-1][k] | k<p,t[k]<t[p]},所以在求解opt[i][j]时,对于k<p,我们不用再比较opt[i-1][k] |,他们的最大值就等于opt[i][p]-1,所以我们可以记录最大的p,然后在求解opt[i][j]时,只对大于p的k作比较,另一方面,如果对于t[p]与t[k]之间的t的元素,我们显然不需要考虑那些不小于t[j]的,又因为t[j]=s[i],所以实际上我们只需要取max{opt[i-1][k] | p<k<j,t[k]<s[i]}与opt[i][p]-1的最大值,鉴于此,我们得到如下的做法:
在每次内层循环(求解j)前,维护一个mx变量,它维护max{opt[i-1][k] | k<j,t[k]<t[j]=s[i]}的值,然后循环j,如果遇到t[j]<s[i],则更新mx=max{mx,opt[i-1][j],当出现t[j]=s[i]时,有opt[i][j]=mx+1。
这样时间复杂度降为O(n^2)。
刚开始的时候记录路径用了一维的,CF上AC了,不过POJWA了,后面改用二维,顺便学习了CF上大神的代码,用pair记录路径,这东西真是好东西,哈哈,又学到一个新东西~~~不过POJ上RE了,发现是有个变量忘记初始化了
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <utility>
using namespace std;
#define MAXN 505
int a[MAXN],b[MAXN];
int dp[MAXN][MAXN],m,n;
pair<int,int> pre[MAXN][MAXN];
void dfs(int i,int j)
{
if(!i||!j) return;
dfs(pre[i][j].first,pre[i][j].second);
if(a[i]==b[j]) printf("%d ",b[j]);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d",&b[i]);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
int p=0;
for(int j=1;j<=m;j++)
{
if(a[i]>b[j]&&dp[i-1][j]>dp[i-1][p]) p=j;
if(a[i]!=b[j])dp[i][j]=dp[i-1][j],pre[i][j]=make_pair(i-1,j);
else
dp[i][j]=dp[i-1][p]+1,pre[i][j]=make_pair(i-1,p);
}
}
int ans=0,index=0;
for(int i=1;i<=m;i++)
if(dp[n][i]>ans)
ans=dp[n][i],index=i;
printf("%d\n",ans);
dfs(n,index);
printf("\n");
}
return 0;
}
Codeforces10D–LCIS(区间DP)的更多相关文章
- 【BZOJ-4380】Myjnie 区间DP
4380: [POI2015]Myjnie Time Limit: 40 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 162 Solved: ...
- 【POJ-1390】Blocks 区间DP
Blocks Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 5252 Accepted: 2165 Descriptio ...
- 区间DP LightOJ 1422 Halloween Costumes
http://lightoj.com/volume_showproblem.php?problem=1422 做的第一道区间DP的题目,试水. 参考解题报告: http://www.cnblogs.c ...
- BZOJ1055: [HAOI2008]玩具取名[区间DP]
1055: [HAOI2008]玩具取名 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1588 Solved: 925[Submit][Statu ...
- poj2955 Brackets (区间dp)
题目链接:http://poj.org/problem?id=2955 题意:给定字符串 求括号匹配最多时的子串长度. 区间dp,状态转移方程: dp[i][j]=max ( dp[i][j] , 2 ...
- HDU5900 QSC and Master(区间DP + 最小费用最大流)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5900 Description Every school has some legends, ...
- BZOJ 1260&UVa 4394 区间DP
题意: 给一段字符串成段染色,问染成目标串最少次数. SOL: 区间DP... DP[i][j]表示从i染到j最小代价 转移:dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k ...
- 区间dp总结篇
前言:这两天没有写什么题目,把前两周做的有些意思的背包题和最长递增.公共子序列写了个总结.反过去写总结,总能让自己有一番收获......就区间dp来说,一开始我完全不明白它是怎么应用的,甚至于看解题报 ...
- Uva 10891 经典博弈区间DP
经典博弈区间DP 题目链接:https://uva.onlinejudge.org/external/108/p10891.pdf 题意: 给定n个数字,A和B可以从这串数字的两端任意选数字,一次只能 ...
随机推荐
- MVC-内容详情页显示内容
@model InfoDataProvider.DataModel.FAQ_ContentUser 内容Content字段:如果里面有html标签. @Html.DisplayFor(p => ...
- 成为Java GC专家(3)—如何优化Java垃圾回收机制
为什么需要优化GC 或者说的更确切一些,对于基于Java的服务,是否有必要优化GC?应该说,对于所有的基于Java的服务,并不总是需要进行GC优化,但前提是所运行的基于Java的系统,包含了如下参数或 ...
- CODEVS 1004四子连棋
[题目描述 Description] 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑 ...
- 关于 Java 性能监控您不知道的 5 件事,第 1 部分
责怪糟糕的代码(或不良代码对象)并不能帮助您发现瓶颈,提高 Java? 应用程序速度,猜测也不能帮您解决.Ted Neward 引导您关注 Java 性能监控工具,从5 个技巧开始,使用Java 5 ...
- python的split用法
Python中没有字符类型的说法,只有字符串,这里所说的字符就是只包含一个字符的字符串!!!这里这样写的原因只是为了方便理解,仅此而已. 1. 按照某一个分隔符分割一个字符串: >>> ...
- Cannot generate SSPI context---MS SQL ERROR
http://www.cnblogs.com/newr2006/archive/2011/08/25/2153253.html Additional error information from SQ ...
- HDU Traffic Real Time Query System
题目大意是:对于(n, m)的图,给定边a, b查询从a到b要经过的割点的最少数目. 先tarjan算法求双连通然后缩点,即对于每个割点将周围的每个双连通看成一个点与之相连.然后求解LCA即可,距离d ...
- 配置Pycharm3.4.1调试edX Devstack
前提: 1.安装好Ubuntu 2.在Ubuntn上利用vagrant+VirtualBox 搭建好了edX Developer Stack,并能成功访问 3.在Ubuntu下安装好了Pycharm- ...
- S5PV210的IRAM应用
准备分析 IRAM的大小96k,其实前两个程序都在这里运行的,程序都小于16K.要实现的是从把IRAM从的前16k从IRAM的起始地址0xD0020000拷贝到0xD0024000 处,调用mai ...
- WPF——绑定数据库数据(Listview)
一.首先先画一个窗体,放进一个Listview 然后给每列起好名字,并且绑定的数据是临时表的列名 二.造一个临时表用来存储数据,并且将扔进去的Listview绑定到这个临时表DataTable上面 p ...