动态规划入门
dp:
dp的策略:
1.设计状态
状态设计原则:
要把变量与待求解的东西紧密结合起来
比如说
lis:
最长递增子序列的长度,(不一定连续)
如果设计状态为1~i中最长递增子序列的长度,那么转移有
f(i)=max(f(i-1),以i为结尾的最长递增子序列的长度)
难以转移
但是如果我设以i为结尾的最长递增子序列的长度
就便于转移了
dp(i)=max(dp(j))+1 (1<=j<=I && a[j]]<=a[i])
另外,一定状态能包含问题的所有信息
比如说在网格上可以朝上 下 右3个方向走,但是要求不能重复走,求走的路径上权值的和最大化
如果设计从1,1走到x,y的权值和的最大值,那么无法保证不重复走,如果判重,那么就不对了
应该设计从1,1到x,y的权值和的最大值,且是从k方向走过来的,这样转移时只要不走回去就不会重复
2.状态转移方程
就是暴力枚举,但不是重新生成,而是用之前算过的状态来推出当前的状态,不一定dp[i]之前的状态就是dp[i-1],可以再往前,要暴力枚举,找出最优答案
3.原问题的解:
写出转移式后思考原问题是哪一个状态
注意不一定这个状态就是确定的,如果以不同的为起点,那么最后可能要枚举起点确定最优值,而这时记忆化搜索就不是那么好用的
4.边界:
到达目标状态时,超出边界范围时,无解时,注意多个边界且答案不同时边界的判断先后顺序!!
5.判重:
记忆化搜索时,要用一个数组来记录已经计算过的状态以减小枚举量,但是如何判断状态已经被计算过呢?
不要在记录状态的数组上记录状态是否被计算过,另开一个vis数组,计算过后置为1,初始化为0,!!!
如果是3.这样枚举起点确定最优值还要用记忆化搜索,那么每一次计算完后vis数组和记录状态的数组不要清空!!
如果清空就重复计算了!!
6.选择:
区间dp 背包 线性dp 常用递推
网格dp 不便于转移的dp 且对复杂度要求不高 常用记忆化搜索
其实记忆化搜索某种意义上比递推快,尤其是图上问题
因为我要求 的点如果与某个点不联通,那么就不用搜索那个点,而递推就都要算一遍
7.滚动数组
如果答案只依赖于i-1的答案,那么相应的一维数组就可以去掉,但是一定注意去掉后的枚举顺序,常用于递推!!
黄粱一梦,终是一空
本文来自博客园,作者:hicode002,转载请注明原文链接:https://www.cnblogs.com/hicode002/p/19526795

浙公网安备 33010602011771号