【动态规划】【RQNOJ】大地的秘密

该博客介绍了如何使用动态规划和优化技巧解决一道关于最长公共子序列(LCS)的问题。在神秘森林的谜题中,通过找到两个序列的LCS,可以确定最少移动木偶的次数。博客详细阐述了动态规划方程的优化过程,包括使用二分查找和维护最长上升子序列,从而实现O(n log n)的时间复杂度解决方案。
摘要由CSDN通过智能技术生成

题目描述

题目背景
在你的帮助之下,三仙兽终于弄清楚了到北京的道路,于是他们收拾一下行装,出发了。

第一站他们要经过被成为“米不亚亚亚亚尔”的神秘森林,由于有蓬絮这位走迷宫的高手打头阵,前进的道路变平坦了很多。但当他们来到这片森林的核心地带时,还是遇到了一点点小麻烦……

题目叙述
现在他们位于神秘森林的核心部位,面前有两条主要的大道,不用说,一条通向光明,一条通向黑暗。大家当然想奔向光明,远离黑暗,可是蓬絮研究了半个时辰也研究不出个所以然。

倒是细心的花楹发现了线索,她在地上搜寻时,发现了遗落在草丛里的一张纸,纸上如是写道:

致想要寻找出口的人们:
  这里必须你们真正了解大地的运行规律,才能破解难关。
  现在,你们只需要拿这这张纸,大喊一声:“哇呱呱呱呱呱呱呱呱呱呱~”,你们前方的地面上就会出现很多的木偶士兵,他们外貌各异。你们必须把他们排布成东边一棵松树上刻纹中写出的阵列,正确的出口才会显露出来。
  正确的答案就在你们面前,只看你们能不能把握咯。

      ——米不亚亚亚亚尔之主:巴罗罗罗罗列吉

没办法,虽然这张破破烂烂发着臭气的纸看上去不像真的,死马当作活马医,三人还是照做了。没想到咒语刚说完,前方“嗡~”的一声起了巨大的烟雾。等到烟消云散,三兽定睛一看,地上果然出现了数不清的人偶。

他们开始相信这一张纸的真实性了,动作快的勇气赶忙找到附近的一棵松树。果然,上面也刻着数不请的人偶图案。

现在的任务就是如何调整木偶的顺序了。整个木偶群可以看成一列排布的,所有的 n 个木偶不尽相同,编号为 1-n。由于仙兽功力有限,每次施法只能把一个木偶移动到另两个木偶之间(可以移到队头和队尾)。

经过三个时辰的仔细研究,勇气已经把所有的木偶都正确编号完毕(勇气:累死俺也~她们两个都不干事的……)。现在他需要你告诉他,要完成调整最少需要移动多少次木偶,这样来给他个心里准备……

数据范围
对于 60% 的数据,n <= 1000
对于 100% 的数据,n <= 100000

输入格式

三行,第一行一个整数 n,表示有 n 个木偶。
第二行,n 个整数(1-n),表示初始时木偶的排布。
第三行,n 个整数(1-n),表示目标木偶的排布。

输出格式

一行,一个整数,表示最少移动次数。


样例解释
先把 1 移动到 10 后面,后面 2-9 每个数移动到 10 和 1 中合适的位置,则 10 不需要移动,共移动 9 次。

样例输入

样例输出

三维状态图像

 

 


 

引用wish大牛的题解:

 这一题考察动态规划及其优化。

很显然,每一个人偶最多只需要移动一次便可到达正确位置。但是从样例中可以看出,有一些人偶是不需要动的,那么最终的答案便是 n 减去不需要移动的人偶数。

我们需要让不需要移动的人偶数尽可能大,那么它最大能到多大呢?相信大家已经看出来了,它的最大值便是两个序列的最长公共子序列(LCS)的长度。这样,我们成功地把这个问题转换为 LCS 问题。

LCS 的经典方程大家都知道:
设两个序列为 a、b,用 f[i, j] 表示第一个序列的前 i 个数,和第二个序列的前 j 个数的最长公共子序列的长度。
若 a[i] = b[j],则
f[i, j] = max{f[i - 1, j - 1] + 1, f[i, j - 1], f[i - 1, j]}
若 a[i] <> b[j],则
f[i, j] = max{f[i, j - 1], f[i - 1, j]}
边界条件:
f[0, j] = 0
f[i, 0] = 0

但是这样的算法是 O(n^2) 的,对于高达 100000 的 n,无论是时间还是空间都无法满足要求,虽然可以采用滚动数组解决空间问题,但是时间问题还是不能解决。

众所周知一般 LCS 问题的最优的时间复杂度即为 O(n^2),那还有什么可以优化的余地呢?这时,我们要利用数据的稀疏性来进行优化。

观察上面的方程,我们发现,只有当 a[i] = b[j] 的时候 f 的值才会增加。而原数据是 n 的两个排列,因而只有 n 个相等点!

抓住这一点我们就可以优化动态规划方程。我们设在第一个序列中与 a[i] 相等的 b[j] 点的下标为 pair[i],那么有:

f[i, pair[i]] = max{f[j, pair[j]}+1 (j <= i, pair[j] < pair[i])

这样,我们只需要保存出长度为 i 的公共子序列的最小下标 j,再用二分查找维护即可。{即类似LIS问题的优化,求pair[a[i]]的最长上升子序列。}

空间复杂度 O(n),时间复杂度 O(nlgn)。

 

一次AC。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值