专栏文章

题解:P11827 [TOIP2024] 大步小步向前走

P11827题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipzre98
此快照首次捕获于
2025/12/03 20:36
3 个月前
此快照最后确认于
2025/12/03 20:36
3 个月前
查看原文

前言:此题解为搬运官方题解,非原创

正文:

仅考虑最大步使用次数

当我们仅需要考虑最大步法使用次数最多时,可以定出以下状态:dp[i]=vdp[i] = v,其中:
  • ii 为第 ii 个非坑洞坐标。
  • vv 为落脚在第 ii 个非坑洞坐标时,可使用最大步法的最多次数。
对于转移,我们能简单地枚举可用步法,去看可以从哪座非坑洞坐标跳到 ii,总时间复杂度为 O((en)×k)3×105O((e - n) \times k) \le 3 \times 10^5

考虑所有的步法使用次数

这里的做法意外的简单,我们使用同样的状态转移:dp[i]=vdp[i] = v,但对于 vv,我们将其定义为一个长度为 kk 的阵列,其中 v[i]v[i] 的值代表着第 ii 种步伐的使用次数。
如此一来,贸然进行相同的转移手段确实能得出解答,但想象上的时间复杂度为 O((en)×k2)O((e - n) \times k^2),这里存在两种优化方式:

只储存有使用到的步法种类

注意到落脚在 ii 时,至多只有 O(i)O(\sqrt i) 种使用到的步法种类,利用 std::vector 等数据结构储存并进行字典序比较,就可以用 O((en)×k×e)O((e - n) \times k \times \sqrt e) 的时间复杂度通过本题。

只针对合法转移进行计算

实际上,只要在转移时忽略那些会转移到坑洞处的步法,总时间复杂度就会是 O((en)×min(en,k)×k)O((e - n) \times min(e - n,k) \times k)。由于 min(en,k)3×105min(e - n,k) \le \sqrt {3 \times 10^5},所以能够通过本题。
该时间复杂度是怎么得出的呢? 上述算法的花费时间为转移次数乘上 kk ,也就是说我们宣称总共的转移次数只有 O((en)×min(en,k))O((e - n) \times min(e - n,k)),而这里有一个很自然的结论:对于一个非坑洞处,合法的转移次数会同时被其他非坑洞处的个数 ene - n、以及步法数 kk 限制住。
该方法也是修改起来最为简单又容易忽略其时间复杂度正确性的做法。

解答的回溯

以上提到的算法都需要在最后回溯出 dp 最佳解的转移过程,一个简单的方法便是直接对每个状态再纪录一个当前最佳解的转移来源,就可以从最终解答一路查表回到初始状态。

一些题外话

实际上,可以利用一些哈希技巧搭配线段树等资料结构来维护每个 dp[i]dp[i] 的步法使用次数,并让两种步法次数的大小关系在数据结构上二分搜“最长共同前缀”来用 O(logk)O(\log k) 的时间复杂度完成比较,总时间复杂度可以进一步优化到 O((en)×klogk)O((e - n) \times k \log k)。但由于该算法常数较大,在一般范围下不太能与前述的算法分出胜负。

评论

0 条评论,欢迎与作者交流。

正在加载评论...