一些前 k 优化问题
前 优化问题
shopping plan.
主要探讨关于「求前
原理类似于
而最主要的问题是:
- 每个状态都能通过该拓展方式得到,即最后是能不漏的将所有状态拓展到的。
- 从当前状态拓展到后继状态时,权值(或者状态的答案)要单调(就像普通的
不能跑有负权的图一样)。 - 每个状态可能被重复到达,我们需要一个方法去重,一般可以在拓展时加钦定使得每个状态的到达方法是唯一的,或者手动去重。
Shopping Plans on Multiset
-
给定一个可重集
,定义他的一个子集 是合法的,当且仅当 ,求出前 小的合法「子集和」。 。
可以先考虑当
考虑构造一种拓展方式能不漏的覆盖所有状态,对于一个的合法的状态,我们可以将最左的可以向右移动的数向右移动若干位,但是不能跨越已选的数,这样显然覆盖了所有状态而且还满足每种状态的到达方法是唯一的,即满足不重不漏。
但是这样每次拓展是
那么怎么记录状态呢,朴素的想,可以用二进制,但是显然不对且无法优化,那么我们可以定义
那么转移有两种:
- 将当前移动的数再往后移一位,显然这需要
,即 。 - 将当前移动的数确定下来,移动的数变为前一个,即
,然后你就发现当前的状态会被重复计算,那我们只好强制给前面那个数移一位了,即 ,限制为 。
初始化很显然选最左的
但是啊,就有一个问题了,我们一种方案(决策)确实可以对应唯一的状态,但是我们的状态并不能对应唯一的方案啊。
比如
事实上,我们前面强调了每种决策由唯一的拓展路径到达,所以并不会导致重复,所以通过这个可以注意到,我们的状态并不像有一些的 dp 一样,一种决策对应唯一的状态,一种状态也对应唯一的决策,而是决策能对应唯一的状态,而状态并不能对应唯一的决策。
那么对于
Shopping Plans on Arrays
-
给定
个数组,要求每个数组中恰好选一个数,求前 小的方案。 。
其实类似上面,本质上就是要构造出一个方法使得每种决策被不重不漏的覆盖的一个小根堆。
显然首先给每个数组内部从小到大排序,我们考虑按顺序确定选什么。
比如我们可以定义状态
转移:
- 第
行换成选第 个, 。 - 确定了第
行就选 ,换到下一行, 。
但是这样的状态问题多多啊,虽然确实不漏,但是会算重复。
比如一种决策
针对这个,我们可以先默认每行的第一个被选,然后将
那么决策
但是
那么我们将这
什么,你说有数组就一个数,那单领出来即可。
复杂度
Shopping Plans
- 给定
个数组,每个数组选的数的个数必须位于 ,求前 小的方案,没有输出 。
其实就是上面两个东西套起来,每个数组看成一个黑盒,里面按照 Shopping Plans on Multiset 得到新的合法方案,外层套 Shopping Plans on Arrays,动态记算,外层需要数时再让内层算即可。
PS:
-
时,要将 加入答案,再将 。 -
的情况,理性特判。 -
状态转移时的各种边界。
-
ans=A1,Q.push((Node2){ans+a[1].y[2]-a[1].y[1],1,2}); A1 为那些只有一种选择方案的行的和
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现