CF10D/POJ2127 LCIS解题报告
前言
期末考试前的最后一篇题解,希望期末考 rp++
奇怪,为什么在CF上能过的代码到POJ上就 听取WA声一片 (不管了)
题目思路
LCIS模版O(n²)+方案记录(递归输出)
LCIS
基础方法
简单易想的方法:直接将LCS和LIS简单相加,复杂度O(n³)
for (int i = 1; i <= l1; i++)
for (int j = 1; j <= l2; j++)
if (a[i] == b[j]) {
for (int k = 0; k < j; k++)
if (b[k] < a[i])
f[i][j] = max (f[i][j], f[i-1][k] + 1);
}
else f[i][j] = f[i-1][j];
时间优化dp
不难看出,状态转移的时候 f 数组的第一维都是由 i-1 转移过来的, 所以不必枚举每一个 k,可以用一个数把之前的最佳方案记录下来
当 i,j 满足a[i] > b[j]时,f[i-1][j]可以去更新最优方案 (因为b[j] < a[i] 时,可以构成上升序列)
#define f(i,a,b) for (int i = a; i <= b; i++)
f (i, 1, l1){
int tmp(0); //tmp记录最优解的值
f (j, 1, l2){
f[i][j] = f[i-1][j];
if (a[i] > b[j]) tmp = max (tmp, f[i-1][j]); //如果满足条件,更新最优方案
if (a[i] == b[j]) f[i][j] = tmp + 1; //如果两个数相等,答案为之前的最优情况+1
ans = max (ans, f[i][j]);
}
}
空间优化dp
因为状态转移的时候 f 数组的第一维都是由 i-1 转移过来的,所以不但在时间上可以记录最优策略来优化,空间上也可以省去第一维。
在代码实现时直接将数组第一维删去即可
#define f(i,a,b) for (int i = a; i <= b; i++)
f (i, 1, l1){
int tmp(0); //tmp记录最优解的值
f (j, 1, l2){
if (a[i] > b[j] ) tmp = f[j]; //如果满足条件,更新最优方案
if (a[i] == b[j]) f[j] = tmp + 1;
//如果两个数相等,答案为之前的最优情况+1
ans = max (ans, f[j]);
}
}
路径记录
基础方法
用一个数组 w[i][j] 来表示 f[i][j] 以 b[j] 为结尾的方案的序列的上一个数的位置。
例如样例中,样例输出 3 5 6 中,以 6 为结尾的方案的 w 数组中存的就是数字 5 的位置
#define f(i,a,b) for (int i = a; i <= b; i++)
f (i, 1, l1){
int tmp(0), k(0); //tmp记录最优解的值,k记录位置
f (j, 1, l2){
f[i][j] = f[i-1][j], w[i][j] = w[i-1][j];
if (a[i] > b[j] and f[i-1][j] > tmp)
tmp = f[i-1][j], k = j; //如果满足条件,更新最优方案
if (a[i] == b[j]) f[i][j] = tmp + 1, w[i][j] = k;
//如果两个数相等,答案为之前的最优情况+1,w 改为记录的最优方案的上一个位置
ans = max (ans, f[i][j]);
}
}
空间优化
和上面求解LCIS的最长长度的空间优化一样,w 数组的第一维在状态转移的时候,i 都是由 i-1 转移过来的,因此也可以去掉一维
#define f(i,a,b) for (int i = a; i <= b; i++)
f (i, 1, l1){
int tmp(0), k(0); //tmp记录最优解的值,k记录位置
f (j, 1, l2){
if (a[i] > b[j] and f[j] > tmp)
tmp = f[j], k = j; //如果满足条件,更新最优方案
if (a[i] == b[j]) f[j] = tmp + 1, w[j] = k;
//如果两个数相等,答案为之前的最优情况+1,w 改为记录的最优方案的上一个位置
ans = max (ans, f[j]);
}
}
方案输出
输出时先枚举每一个以 b[j] 结尾的答案与最优解对比,从而找出最优解的最后一个数(注意:要特判答案是否存在长度>0的序列,若没有不用输出,我为此WA了两次)
if (ans) //特判是否存在长度>0的序列
f (i, 1, l2)
if (f[l1][i] == ans) {print(i); break;} //找到最优解的末尾位置并输出序列
找到位置后递归输出
void print (int p) {
if (w[l1][p]) print(w[l1][p]); //如果之前还有数,先输出之前的数
printf ("%d ", b[p]);
}
优化效果

可以看出,优化后空间极其节省(虽然两种都能过)
至于时间上的差异emm······ 连续交两次同样代码跑出来的时间都差好多
完整代码
未优化
#include <cstdio>
#include <iostream>
using namespace std;
#define f(i,a,b) for (register int i = a; i <= b; i++)
int l1, l2, a[538], b[538], f[538][538], w[538][538], ans;
void print (int p) {
if (w[l1][p]) print(w[l1][p]); //如果之前还有数,先输出之前的数
printf ("%d ", b[p]);
}
int main() {
scanf ("%d", &l1);
f (i, 1, l1) scanf ("%d", a + i);
scanf ("%d", &l2);
f (i, 1, l2) scanf ("%d", b + i);
f (i, 1, l1){
int tmp(0), k(0); //tmp记录最优解的值,k记录位置
f (j, 1, l2){
f[i][j] = f[i-1][j], w[i][j] = w[i-1][j];
if (a[i] > b[j] and f[i-1][j] > tmp)
tmp = f[i-1][j], k = j; //如果满足条件,更新最优方案
if (a[i] == b[j]) f[i][j] = tmp + 1, w[i][j] = k;
//如果两个数相等,答案为之前的最优情况+1,w 改为记录的最优方案的上一个位置
ans = max (ans, f[i][j]);
}
}
printf ("%d\n", ans);
if (ans) //特判是否存在长度>0的序列
f (i, 1, l2)
if (f[l1][i] == ans) {print(i); break;} //找到最优解的末尾位置并输出序列
return 0;
}
优化后
#include <cstdio>
#include <iostream>
using namespace std;
#define f(i,a,b) for (register int i = a; i <= b; i++)
int l1, l2, a[538], b[538], f[538], w[538], ans;
void print (int p) {
if (w[p]) print(w[p]); //如果之前还有数,先输出之前的数
printf ("%d ", b[p]);
}
int main() {
scanf ("%d", &l1);
f (i, 1, l1) scanf ("%d", a + i);
scanf ("%d", &l2);
f (i, 1, l2) scanf ("%d", b + i);
f (i, 1, l1){
int tmp(0), k(0); //tmp记录最优解的值,k记录位置
f (j, 1, l2){
if (a[i] > b[j] and f[j] > tmp)
tmp = f[j], k = j; //如果满足条件,更新最优方案
if (a[i] == b[j]) f[j] = tmp + 1, w[j] = k;
//如果两个数相等,答案为之前的最优情况+1,w 改为记录的最优方案的上一个位置
ans = max (ans, f[j]);
}
}
printf ("%d\n", ans);
if (ans) //特判是否存在长度>0的序列
f (i, 1, l2)
if (f[i] == ans) {print(i); break;} //找到最优解的末尾位置并输出序列
return 0;
}
CF10D/POJ2127 LCIS解题报告的更多相关文章
- CH Round #56 - 国庆节欢乐赛解题报告
最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...
- 二模13day1解题报告
二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...
- BZOJ 1051 最受欢迎的牛 解题报告
题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4438 Solved: 2353[S ...
- 习题:codevs 2822 爱在心中 解题报告
这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...
- 习题:codevs 1035 火车停留解题报告
本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...
- 习题: codevs 2492 上帝造题的七分钟2 解题报告
这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...
- 习题:codevs 1519 过路费 解题报告
今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...
- NOIP2016提高组解题报告
NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合
- LeetCode 解题报告索引
最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中...... ...
随机推荐
- BZOJ2120:数颜色
浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html 题目传送门:https://www.lydsy.com/JudgeOnline/prob ...
- 洛谷【P1138】第k小整数
题目传送门:https://www.luogu.org/problemnew/show/P1138 桶排: 对于值域在可以接受的范围内时,我们可以用不依赖比较的桶排去将数据排序.因为桶排不依赖比较排序 ...
- 洛谷【P1236】算24点
我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html 题目传送门:https://www.luogu.org/problemnew/show/P ...
- Azure上部署FTP服务
FTP是个比较复杂的协议,其协议分为控制层和数据层,工作模式分为主动和被动两种模式. 在默认的Active模式下其工作原理如下: 可以看到,客户端发起FTP的请求道服务器端,FTP的端口是21.用户在 ...
- n文件的上传和下载,struts2和springmvc
首先,struts2的上传下载的配置 因为struts2是配置的上传的拦截器,很简单的步揍就可以上传, 首先是配置struts的action映射 <!-- 4. 修改上传文件的最大大小为30M ...
- mina中的发送延时
由于项目需要,用到了 mina 框架进行 tcp 通讯.我是初次接触 mina,于是从 Hello world 开始学习了 mina .期间遇到了一个奇怪的发送数据的延迟问题,解决的过程是曲折的,但找 ...
- Web Form要“jquery”ScriptResourceMapping。请添加一个名为 jquery (区分大小写)的 ScriptResourceMapping。”的解决办法。
1.先将aspnet.scriptmanager.jquery.dl 复制到bin (网站根目录下的bin文件夹找不到,看看下面的图片中点击[显示所有文档]) 文件夹下. 2.在网站根目录下s ...
- 安装Ruby On Rails时运行“gem install rails”没有反应怎么办?
这两天在我的mac机上安装Ruby On Rails,感觉很爽,似乎在使用一个Windows和Linux的结合体,要界面有界面,要命令行有命令行. 不过安装Ruby On Rails的过程中遇到一个问 ...
- Spirng+In+Action(Craig Walls Ryan Breidenbach)
目录 1.开始Spring之旅(简介) 2.装配Bean(IoC) 3.创建切面(AOP) ... 第一章:开始Spring之旅 1.1 为什么使用Spring:简化了企业级系统开发. 1.1.1 j ...
- adroid 分辨率适配
(1)drawable-hdpi里面存放高分辨率的图片,如WVGA (480x800),FWVGA (480x854) (2)drawable-mdpi里面存放中等分辨率的图片,如HVGA (320x ...