扩大
缩小

【NowCoder 补全计划】动态规划

NC21303 删除括号

给两个合法括号串 s,t,每次可以从 s 删除一对相邻的括号 (),问是否可以从 s 变成 t

f(i,j,k) 表示当前原串到 i,匹配串到 j,且原串略过 k 个左括号(且这些左括号还未匹配),是否可能成立。

  • 如果 k=0,且 si=tj,那么 f(i1,j1,k)f(i,j,k)
  • 如果原串第 i 位是 (,那么 f(i1,j,k1)f(i,j,k)
  • 如果原串第 i 位是 ),那么 f(i1,j,k+1)f(i,j,k)

最后判断 f(lens,lent,0) 是否为 true 即可。时间复杂度 O(n3)

NC21314 CodeForces

如果题目分数没有随时间变动,那么直接背包就好了。

但是现在不是这样,由于背包枚举物品是有次序的,如果两题都做,那么背包会默认优先做编号小的题目,这未必是最优的。

因此我们需要改变题目的枚举顺序,此处可以贪心。

假设当前两题 i,j (i<j) 的分数减少速度是 vi,vj,做题时长为 ti,tj

那么先做 i 后做 j 的损失是 viti+vj(ti+tj),先做 j 后做 i 的损失是 vjtj+vi(ti+tj)

我们想让损失变小,需要满足 viti+vj(ti+tj)vjtj+vi(ti+tj),化简得到 vjtivitj

按照这个顺序重排题目,就可以上背包了。

NC13249 黑白点

一棵全是白点的树,每次可以选择一个白点 i,将 i1 的简单路径上距离小于 ki 的点全部染黑,问最少染多少次可以将树全部染黑。

首先有一个错误的贪心:叶子节点一定要染色,然后每次向上跳,跳到染不到的时候继续染色。

它错误的原因在于,i1 路径上距离小于 ki 的点 j,可能有更大的 kj,走得更远。

因此我们在从子节点上传到父节点时,要传递一个信息,就是当前是否需要被迫染色。

在还不急着染色的时候,我们在链上的每个点计入备选方案,等到必须染色时,把备选方案里从当前位置上升距离最远的点设置为染色点。

为了完成这个想法,我们记 f(i) 表示当前还上升的最大空间(新的点染色前),k(i) 记以当前的最远染色距离(所有备选方案的最远距离)。

对于父节点 u 和子节点 v,有 f(u)=max{f(v)1}k(u)=max(k(u),max{k(v)1})

如果当前 f(u)=0,代表此时必须要染色一个点,我们直接取出备选方案的最优解,即 f(u)=k(u)

求出必须染色的点数即可。

NC21337 牛牛的回文串

你可以花费一定的代价在字符串加入指定字符、删除指定字符、转换指定字符。问构造出回文串的最小代价。

一眼DP,然后大力分讨:

  • 首先转换指定字符可能存在间接转换,即 ab,bc 的情况,这时我们需要像求 floyd 一样求出任意两个字符转换的最小代价。
  • 假设 c(i,j) 代表字符 ij 的最小代价。像区间 DP 一样由外向内处理区间 [i,j]
  • 如果 si=sj,我们可以无代价转移。
  • 如果 sisj,选择以下这几种方案进行操作:
    • 直接将 si 转成 sj,或 sj 转成 si
    • sisj 都转成一个相同的字符;
    • sisj 直接删去其一;
    • sj 右侧插入一个与 si 相同的字符;
    • 在 sj 右侧插入一个与 si 不同的字符,并将这个不同的字符转为 si
    • si 左侧插入一个与 sj 相同的字符;
    • 在 si 左侧插入一个与 si 不同的字符,并将这个不同的字符转为 sj

时间复杂度可以做到 O(26n2+263)

posted @   HoshizoraZ  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示