P1439-DP【绿】
轻敌了啊...题目一共只有几句话但我却忽略了一个重大信息...
总之我显示写出了时空复杂度都是n^2级别的朴素递推算法,这没什么,基本功而已,然后50分
我试了试滚动数组,把空间复杂度降到了n级别,但没什么用,解决了MLE但仍然TLE。
后来我想到记搜应该能算的更快,毕竟有些用不到的点用搜索就不用算了,但是空间不允许开n^2,所以我先是试着只抛弃那些没用到的点,即搞了一个pos->int的map,pos是一个自定义数据结构含有两个int表示数组下标。期间遇到编译错误, 然后就学到了一个知识点那就是unordered_map不需要比较运算符但是map需要比较运算符,也就是说如果自定义数据结构那你就必须给出operater<,更重要的是还必须声明这是一个const成员函数,即写成bool operator<(const pos & b)const的形式,后面这个const表示这个成员函数绝对不改数据,不加它就报错....总之解决问题后成功用上了这个做法,然后好像是60分了
再然后我想不如利用更多的空余空间,谁说记搜和滚动数组不能一起用,于是我成功了,分别基于动态数组和map各设计了一套空间复杂度极低的记忆化搜索算法,但我TMD写完之后才意识到不是记搜用不了滚动数组,而是记搜用滚动数组将不得不负责清理数组而不能无脑覆盖,因为记搜的调表顺序不同,可问题在于清理数组是一个O(n)级别的操作这就导致滚动数组式的dp几乎铁定耗时比递推滚动数组要满,空间复杂度还只能勉强一样,那显然还不如最开始的写法呢...果然,只有十分二十分....越写越回旋
写的我都饿了,就去看了看题解,才发现我忽略了一个条件那就是两个数列都是1~n的全排列!这道最长公共子序列可以转换成最长上升子序列...
啊啊啊啊啊啊所以最后我没做出来这道题在于我一开始就想偏了,普通的最长公共子序列压根就不存在!不存在!O(n^2)的算法!!!我一直在寻找一个不存在的东西当然一无所获...
当然也不算是一无所获,毕竟我获得了map、unordered_map相关的更深层的理解和更高的运用熟练度,还意识到了记搜能搞滚动数组但是不应该搞滚动数组...以及尝试用记搜代替递推的方式似乎几乎不可能解决耗时问题...
总之这道最长公共子序列不是一道普通的最长公共子序列题,是一道变了形的最长上升子序列题,那么答案很显然了。
朴素滚动数组DP
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <map>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
int n,a[100000+5],b[100000+5],dp[100000+5],new_dp[100000+5];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i]==b[j]) new_dp[j]=1+dp[j-1];
else new_dp[j]=max(dp[j],new_dp[j-1]);
}
for(int j=n;j>=1;j--)dp[j]=new_dp[j];
}
printf("%d",dp[n]);
return 0;
}
记搜+map-Code
#include <iostream>
#include <map>
using namespace std;
int n,a[100000+5],b[100000+5];
struct pos
{
int x;int y;
pos(){}
pos(int X,int Y){x=X;y=Y;}
bool operator<(const pos & b)const
{
if((this->x)!=(b.x))return (this->x)<(b.x);
else return (this->y)<(b.y);
}
};
map<pos,int> dp;
int dfs(int i,int j)
{
if(i==0||j==0)return 0;
pos && POS=pos(i,j);
if(dp.count(POS)==1)return dp[POS];
if(a[i]==b[j]) return dp[POS]=1+dfs(i-1,j-1);
else return dp[POS]=max(dfs(i-1,j),dfs(i,j-1));
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
printf("%d",dfs(n,n));
return 0;
}
记搜+滚动数组Code1
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <unordered_map>
#include <queue>
#include <cmath>
using namespace std;
int n,a[100000+5],b[100000+5];
unordered_map<int,int>dp;
int dfs(int i,int j)
{
if(i==0||j==0)return 0;
if(dp.count(j)!=0)return dp[j];
if(a[i]==b[j])
{
dp.clear();
return 1+dfs(i-1,j-1);
}
else
{
int ans1=dfs(i,j-1);
dp.clear();
int ans2=dfs(i-1,j);
return max(ans1,ans2);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
printf("%d",dfs(n,n));
return 0;
}
记搜+滚动数组Code2
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
int n,a[100000+5],b[100000+5];
int * dp;
int dfs(int i,int j)
{
if(i==0||j==0)return 0;
if(dp[j]!=-1)return dp[j];
if(a[i]==b[j])
{
delete[] dp;
dp=new int [j];
for(int k=0;k<j;k++)dp[k]=-1;
return 1+dfs(i-1,j-1);
}
else
{
int ans1=dfs(i,j-1);
delete []dp;
dp=new int [j+1];
for(int k=0;k<=j;k++)dp[k]=-1;
int ans2=dfs(i-1,j);
return max(ans1,ans2);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
dp=new int [n+1];
for(int k=0;k<=n;k++)dp[k]=-1;
printf("%d",dfs(n,n));
return 0;
}
P1439-DP【绿】的更多相关文章
- 「疫期集训day4」硝烟
那真是一阵恐怖的炮击(that boomed booms),响亮的炮音(that noise),滚滚的硝烟(that smoke),熊熊的火焰在围绕着我们前进...小心前进(go and be car ...
- P1439 【模板】最长公共子序列(DP)
题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子 ...
- 洛谷 P1439 【模板】最长公共子序列(DP,LIS?)
题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子 ...
- 洛谷-P1439 【模板】最长公共子序列 (DP,离散化)
题意:给两个长度为\(n\)的全排列,求他们的LCS 题解:这题给的数据范围到\(10^5\),用\(O(n^2)\)的LCS模板过不了,但由于给的是两个全排列,他们所含的元素都是一样的,所以,我们以 ...
- DP擎天
DP! 黄题: 洛谷P2101 命运石之门的选择 假装是DP(分治 + ST表) CF 982C Cut 'em all! 树形贪心 洛谷P1020 导弹拦截 单调队列水题 绿题: 洛谷P1594 护 ...
- 【BZOJ-1260】涂色paint 区间DP
1260: [CQOI2007]涂色paint Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 1147 Solved: 698[Submit][Sta ...
- hdu4939 Stupid Tower Defense (DP)
2014多校7 第二水的题 4939 Stupid Tower Defense Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 131 ...
- 洛谷P2014 选课 (树形dp)
10月1日更新.题目:在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分 ...
- 【DP】BZOJ 1260: [CQOI2007]涂色paint
1260: [CQOI2007]涂色paint Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 893 Solved: 540[Submit][Stat ...
- 周赛C题 LightOJ 1047 (DP)
C - C Time Limit:500MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Description Th ...
随机推荐
- 吉特日化MES系统&生产工艺控制参数对照表
吉特日化MES生产工艺参数对照表 工艺编号 PROCE_BASE_TIMER 工艺名称 定时器 工艺说明 主要用于生产工艺步骤过程计时 参数编号 参数名称 参数描述 Prop_Timer_Enable ...
- tensorflow GPU版本配置加速环境
import tensorflow as tf tf.test.is_gpu_available() 背景 环境:Anaconda .tensorflow_gpu==1.4.0 (这里就用1.4.0版 ...
- Logistics Regression (对数几率回归)及numpy实现
Logistics Regression 我们知道线性回归模型可以处理回归问题,但是如何处理分类问题? 对于一个二分类问题,或许我们可以认为w*x+b > 0为正类,其他情况为负类. 那么模型不 ...
- 3D组合地图在数据可视化大屏中的应用
前言 当下数据可视化大屏展示的花样层出不穷,可视化大屏的C位越来越卷,地图的样式已经不再止步于普通的平面地图,在虚拟环境中探索和交互,今天我们要介绍的这一款3D组合地图可以将复杂的数据以直观的方式呈现 ...
- 从零玩转Websocket实时通讯服务之前后端分离版本
前言 公司项目需要用到消息提示,那么WebSocket它来了经过我面向百度的学习,废话不多说直接开干. 后端搭建 一.依赖导入 <dependency> <groupId>or ...
- 中间件是开箱即用的吗?为什么要开发中间件adapter?
本文分享自华为云社区<中间件是开箱即用的吗?为什么要开发中间件adapter?>,作者:张俭. 中间件在很多系统中都存在 在一个系统里面,或多或少地都会有中间件的存在,总会有数据库,其他的 ...
- springboot的启动器
前言 ~ 面试的时候,被问到springboot 官方提供的启动器常见的有哪些?(头大) 正文 ~ 启动器作用: 启动器是为了 适应 一个特定的场景的,里面定义了 这个场景下 需要用到的依赖. 启动器 ...
- k8s主要概念大梳理!
k8s已经成为了绝对热门的技术,一个上点规模的公司,如果不搞k8s,都不好意思出去见人.安装k8s要突破种种网络阻碍,但更大的阻碍还在后面... 我发现,很多k8s的文章,根本不说人话,包括那要命的官 ...
- 斯坦福 UE4 C++ ActionRoguelike游戏实例教程 11.认识GAS & 创建自己的能力系统
斯坦福课程 UE4 C++ ActionRoguelike游戏实例教程 0.绪论 概述 本篇文章对应Lecture 16 - Writing our own Gameplay Ability Syst ...
- 通过鼠标拖拉获取图片原像素的两个点坐标vue
<template> <div> <img class="no-drag" ref="image" src="https ...