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 ... 
随机推荐
- [ABC246A] Four Points
			Problem Statement There is a rectangle in the $xy$-plane. Each edge of this rectangle is parallel to ... 
- Winform  控件库 MaterialSkin.2 使用教程(鸿蒙字体版)
			️MaterialSkin.2 控件库在之前的文章中已经介绍过了,就不啰嗦了 - > Winform 好看控件库推荐:MaterialSkin.2 ️官方库里使用的是 Google 的 Robo ... 
- SpringBoot-Validate优雅的实现参数校验,详细示例~
			1.是什么? 它简化了 Java Bean Validation 的集成.Java Bean Validation 通过 JSR 380,也称为 Bean Validation 2.0,是一种标准化的 ... 
- NetSuite 开发日记:如何管理多环境自定义列表值
			在 NetSuite 中可以创建自定义列表,列表可用于为其他(自定义)记录上的下拉选项列表值. var rec = record.create({ type: 'customrecord_xx' }) ... 
- 使用容器快速在阿里云  ECS  多节点上搭建 Citus 12.1 集群
			阿里云 ECS 机器节点 这里我们使用两台同一区域的 ECS 机器. 机器配置:2 核 2 G.(ps: 阿里云 99 元一年的活动) 一台安装 coordinator(协调器),这里内网 IP 为 ... 
- pytest框架学习-前置和后置setup和teardown
			前置和后置 (1)setup和teardown,方法级 写在类中 方法级,每个用例都会执行setup和teardown. 相当于setup_method和teardown_method (2)setu ... 
- 支付宝 v3 验签如何实现
			上次给大家介绍了 支付宝 v3 自签名如何实现,这次顺便再把验签也写一下. 为什么要验签 说起为什么要验签,如果要详细一点解释的话,可以写很多很多...... 我们就简单一点来解释:验签可以证明接收到 ... 
- ja-netfilte-ja-netfilte
			title: ja-netfilte date: 2022-10-16 16:13:50.339 updated: 2023-02-07 22:58:50.672 url: https://www.y ... 
- Keepass调用Xshell、SecureCRT、RDP、Putty的方法(一劳永逸版)
			依次点击"工具"--"选项"--"集成"--"网址替代"--"添加"--添加"方案&quo ... 
- BUUCTF Web CyberPunk WriteUp
			想直接查看payload的点这里 前言 二次注入(Second-Order Injection)是指攻击者在应用程序中注入恶意数据,然后在稍后的操作或不同的上下文中再次使用该恶意数据,导致安全漏洞.它 ... 
