概念
学习使用递推的前提:一维数组,或者要会使用有限个变量,互相传递数值迭代前进的操作。
引言:一个实际问题的各种可能情况构成的集合,通常称为 “状态空间”,而程序的运行则是对状态空间的遍历。
递推 是程序遍历状态空间的基本方式。由已知的 “问题边界” 为起点,向 “原问题” 正向推导的扩展方式就是递推。
例子:询问有几个苹果,有每个人向上反馈,得到有n个苹果。
例子:Fibonacci数列
例子:兔子繁殖问题,把雌雄各一的一对新兔子放入养殖场中。每只雌兔在出生两个月以后,每月产雌雄各一的一对新兔子。试问,第n个月后养殖场中有多少对兔子。
- 请编程实现一下,兔子繁殖问题,输出前10个月兔子的数量,每行一个数字
- 理解兔子繁殖问题的时候,不建议画很繁杂的图,会容易扰乱思考
- 集合划分方法,分析出递推公式,上个月就有的老兔子 + 这个月出生的新兔子
f(n) = f(n - 1) + f(n - 2)
入门题目
上台阶
//简单
菲波那契数列(2)
//简单
Pell数列
//简单
《一本通》题目
【例3.4】昆虫繁殖
//用一个数组维护成虫数量,用一个数组维护卵的数量
//不开long long见祖宗
【例3.5】位数问题
//从1位数字开始递推,`f[i][0] 表示i位数字,有奇数个3的数字个数;同理,f[i][1]`
【例3.6】过河卒(Noip2002)
//先做1194:移动路线
//马的八个方向的枚举,check()的操作方法(每次进行一次check,判断9次;或者初始化的时候,设置好非法的点,后面递推的时候,避开非法的点),要注意LL
菲波那契数列(2)
//
Pell数列
//
上台阶
//
流感传染
//模拟,一层一层的扩大感染的范围
//注意这个扩散是一层一层的扩散,要注意控制这个一层一层的问题,需要用到标记数组
放苹果
//这个理解有难度,分为
//盘子比苹果多的情况,苹果比盘子多的情况
// 苹果的数量比盘子多的时候:
// 有空盘子,那至少应该有一个盘子剩余:f(m,n-1)
// 没有空盘子,那至少每一个盘子都有一个苹果,去掉n个苹果也是多放法总数不构成影响:f(m-n,n)
// 盘子的数量比苹果的时候:
// 去掉多余的盘子对摆放不构成影响:f(m, m)
// 问题边界
// 手里有0个苹果,就1种放法。(如果手里有1个苹果,这个方法并不唯一,如果面临现有盘子里苹果数量不一样)
// 有1个盘子时候,也只有1种放法,就是有苹果就放这个盘子,没苹果就不放
吃糖果
//打表找规律,然后就了了了
移动路线
//和过河卒题目类似
判断整除
//这道题放在后面做,和《1299:糖果》dp问题类似,和 knapsack problems 判断方案是否可行也类似
//设计问题状态,dp[1...n][0....k-1],表示前i个数,%k余数是0... k-1的可能性
//第 i 个数可能是前 i-1 个数基础上 +a[i] , 也可能是 -a[i]
踩方格
//这道题目,开始锻炼,当前状态是从什么状态转过来的思维方式
//画图理解第一步有三个方向可以走,构成了三个子问题。这三个子问题的特点,和第一步的特点进行对比
//然后再往下走一步看看
//每一步,要么有三个方向选择,要么有两个方向选择
山区建小学
//区间dp,这道题目放在后面做
//int dp[N][N]; //前i个村庄,建立j的小学的最小距离之和
//需要预处理 [i, j] 之间建立一个学校的最小代价
更进一步
五种典型的递归关系:Fibonacci数列,Hanoi塔问题,平面分割问题,Catalan数,第二类Sitring数。这些问题需要初赛前学会。