动态规划学习的一波记录

线性DP

例题*1:

一个公司有三个移动服务员,最初分别在位置1, 2, 3处
如果某个位置(用一个整数表示)有一个请求,那么公司必须指派某名员工赶到那个地方去。某个时刻只有一个员工能移动,且不允许在同样的位置出现两个员工。从p到q移动一个员工,需要花费c(p, q)。这个函数不一定对称,但保证c(p, p) = 0
给出n个请求,请求发生的位置分别为p1~pn。公司必须按顺序依次满足所有请求,目标是最小化公司花费,请帮助计算这个最小花费。N <= 1000, 位置是1~ 200的整数


划分阶段:假设要完成第i个任务,我们只需要考虑的是当前职员所在的位置
通过指派一名服务员,我们可以把状态从 完成i - 1个请求转移到完成i个请求
所以阶段就是“完成任务的数量”
为了计算服务员的花费,我们已知每个服务员的起始位置,最直接的想法是:将三个服务员放在“状态中”
f[i, x, y, z]
完成了前i个请求,服务员分别位于x, y, z是,公司的最小花费
考虑状态转移,显然有三种,就是派三个服务员中的一个去第i + 1个位置
f[i+1, pi+1, y, z] = min(f[i+1, pi+1, y, z], f[i, x, y, z] + c(x,pi+1));
f[i+1, x, pi+1, z] = min(f[i+1, x, pi+1, z], f[i, x, y, z] + c(y,pi+1));
f[i+1, x, y, pi+1] = min(f[i+1, x, y, pi+1], f[i, x, y, z] + c(z,pi+1));
分析算法规模,状态数为1000 * 200^3,不能承受。
仔细观察可发现,在完成第i个请求时,一定有某个员工位于位置pi,只需要阶段i个另外两个员工的位置x,y(注意并不是员工x和y)即可描述状态,处于pi的员工对DP来说是冗余信息
因此,我们就可以用f[i, x, y]来表示完成前i个请求时,其中一个员工位于pi,另外两个员工分别位于x,y时,公司的最小花费
f[i+1,x,y] = min(f[i+1,x,y],f[i,x,y] + c(pi,pi+1));
f[i+1,pi,y] = min(f[i+1,pi,y],f[i,x,y] + c(x,pi+1));
f[i+1,x,pi] = min(f[i+1,x,pi],f[i,x,y] + c(y,pi+1));
设p3 = 0,于是初值可设为p[0,1,2] = 0,目标为p[n,?,?]
启发:
1.求解线性dp问题,一般想确定“阶段”。若“阶段”不足以表示一个状态,则可以把所需的附加信息也作为状态的维度
在转移时,若总是从一个阶段转移到下一个阶段(本题i到i+1),则没有必要关心附加信息维度的大小变化情况(本题x,y,z在转移前后大小不定),因为无后效性已经有“阶段”保证
2.在确定DP状态时,要选择最小的能够覆盖空间的“维度集合”。
若DP状态有多个维度构成,则应检查这些维度之间能否相互导出,用尽量少的维度覆盖整个状态空间,排除冗余维度。

猜你喜欢

转载自www.cnblogs.com/ywjblog/p/8921766.html