目录
暴力
递归
需要尝试所有可能性求解最佳方案的都是可以使用递归的方法进行解决的。下面数的划分是一道经典的在递归中使用一个变量 + for循环控制范围去除重复方案的题目,里面的思路其实写得挺好的可以学习学习。
邮票面值设置(c++-python3 dfs + 动态规划减枝)使用动态规划的方法确定当前位置的搜索上界
明七暗七(c++-python3 数位dp-二分查找 + dfs)
数学
找规律
栈和队列
二分查找
二分查找是在一个有序的数组或者列表中查找某个位置的值是否满足某些条件,通过限制条件来更新左右边界的值
明七暗七(c++-python3 数位dp-二分查找 + dfs)
动态规划
动态规划的核心就是递推,具体来说就是递推方程式的确定(方程式体现的就是状态之间的转移),也即如何利用之前的状态递推当前的状态,对于二维dp最好的解决办法是利用表格填写每一行的数字来找到具体的递推方程式(很多二维的字符串动态规划/背包问题列表格填数字是最容易发现状态之间转移的规律的)。下面的美丽序列是经典的多维dp的题目,理解如何分析题目中动态变化的参数来声明对应维度的dp列表或者数组,每一个维度具体表示的含义,如果进行状态的转移。对于子序列的问题都是可以使用动态规划来做的,尝试将当前的元素添加到之前的序列后面。
被3整除的子序列(python3 动态规划)对于子序列的动态规划思路大部分都是尝试将当前的数字添加到之前的序列后面,一般来说可以使用多层循环进行递推
邮票面值设置(c++-python3 dfs + 动态规划减枝)
背包问题
01背包(python 3 需要理解使用一维dp解决逆序遍历背包容量的含义)
完全背包(python3 一维dp)正序遍历背包容量
codeforces(java-python3 排序 + 01背包)python语言使用元组封装多个属性实现整体排序,java语言使用对象数组自定义排序规则实现整体排序
数位dp
数位dp最常用的是借助于dfs从高位-低位填各个位置上可能的数字,使用一个flag变量来记录当前位是否是最高位的最大数字来控制下一个低位可以填的数字范围是[0,9]还是[0,x],使用dfs搜索比直接求解某一个区间中所有数字中各个位上的数字满足的某些条件耗时要短一点
明七暗七(c++-python3 数位dp-二分查找 + dfs)
下面是y总B站视频关于数位dp的题目:数位dp的题目大部分是求解关于某一个区间满足某一种性质的数的个数。下面的度的数量/数字游戏题目中的模板是类似的。首先需要声明一个数组或者列表来记录组合数或者递归过程的值,使用一个init方法来预处理列表f的值,预处理的过程大部分是使用动态规划进行递推得到的结果,所以这也是数位dp的一个难点。然后使用一个dp方法来求解区间[0, n]的符合题目要求的数目,这样区间[x, y]的数目为f(y) - f(x - 1),首先是使用列表nums存储x中各个位上的数字然后逆序遍历,考虑当前第i位的数字num[i],这一位可以填0~nums[i] - 1,在这个范围中我们可以使用之前预处理的f列表对应位置的值累加到结果中,声明一个last变量来表示上一次某些结果,对于不同的题目last的含义是不一样的需要根据具体的题目具体分析,数字游戏中last表示上一位最后一次填的数字,这样下一位填的数字为last~nums[i] - 1,进入循环的下一个数字的时候相当于是固定了上一次中第i位填数字x的情况。反正对于当前位需要分清理考虑:① 当前位为0~nums[i] - 1 ② 当前位为nums[i],一般进入下一个循环的时候表示就是上一位填nums[i]的情况。最后还需要考虑i = 0的情况判断是否需要加上最后一个方案。
windy数(python3 数位dp)当首位是0的时候由于题目的限制条件会对结果造成影响所以需要额外处理这种情况。
状压dp
使用二进制的0与1表示对应的状态,这样可以表达出题目复杂的状态,有的时候可以减少时间复杂度。其中状压dp涉及到相关的位运算操作,例如计算二进制中1的数目:while x: if x & 1: count+=1; x >>= 1,检查二进制数字是否存在连续的1,例如i & (i << 1)检查二进制数字是否存在两个连续的1,n个连续的1那么使用i & (i << (n - 1))。
最短路径
单源最短路径(求解从起点到各个顶点的最短路径)算法:dijkstra(给定的图为正边)spfa算法(给定的图中存在负边,spfa算法可以用来判断图中是否存在负环)。有时候从源点到终点的题目可以直接使用动态规划进行求解。