OI退役笔记-006:基础算法(一)递推

递推问题求解过程:
过程
确定状态可以看有多少个未知数;
递推关系即将 f[i] 用之前推出的值表示;
最后用程序实现就简单了。

例1. 斐波那契数列

简单,不赘述。

f[1] = 0;
f[2] = 1;
f[i] = f[i - 1] + f[i - 2];

同样,走楼梯问题、多米诺骨牌问题公式相同,因为其递推关系相同

  • 多米诺骨牌问题

走楼梯
yaxi

  • 走楼梯问题
    一个人爬楼梯,每次只能爬1个或两个台阶,假设有n个台阶,那么这个人有多少种不同的爬楼梯方法?

走楼梯问题和多米诺骨牌问题其他解法:

第一列若是一阶或竖格,总共有 1 * f[i - 1] 种算法;
第一列若是二阶或横格,总共有 1 * f[i - 2] 种算法;
f[i] = f[i - 1] + f[i - 2];

例2. 汉诺塔问题
题目
图

如果有 n 个盘子,转换中间时一定有:
第 n 个盘子在 c 柱上,其余盘子在 b 柱上

所以,应先用 f[i - 1] 步将 1 ~ n - 1 的盘子移到柱,用一步将 n 盘移到c柱上,再 f[i - 1] 次将 b 柱上的盘子移到 c 柱上。

所以递推公式是 :

f[1] = 1;
f[i] = f[i - 1] * 2 + 1;

由此可以推导出:

f[i] = qpow(2, i) - 1;

例3. 放球问题
题目

题中有 2 个状态 n、r,所以需要二维数组。
f[i][j] 表示第 i 个球放在 j 个盒子里的方法数;

// i == j
f[i][j] = 1;
//i < j
f[i][j] = 0;
// j == 1
f[i][j] = 1;

第 i 个球,若单独放进一个盒子里,那么前 i - 1个球的、放入了 j - 1 个盒子,方法有 f[i - 1][j - 1] 种;
若第 i 个球和其他球放到一起,那么有f[i - 1][j] 种情况。但是第 i 个球可以放入 j 个盒子中任意一个,所以方法数为 f[i - 1][j] * j

综上,

f[i][j] = f[i - 1][j - 1] + f[i - 1][j] * j;

答案为f[n][r],时间复杂度为 O(n * r)

例4. 错排问题

n个编号为1到n的同学手里都有一本书,n本书互不相同,现在把这n本书收起来,再重新分发给同学,要求每个同学必须都有书,并且每个同学现在拿到的书必须不同于之前手里的那本书,问有多少种分发方案?

f[1] = 0;
f[2] = 1;
f[i] = (i - 1) * (f[i - 1] + f[i - 2]);

例5. 统计二叉树问题
描述
嘿

分析如下:
左右子树
单取一个点作为根节点,其余点中 j 个点作为左节点,剩下的 i - j - 1 个节点就是右节点了。

// i = 0
f[i] = 1;
// i >= 1;

公式
例6. 出栈序列
1 最特殊,用 1 做判断
(1 是最先入栈的,可作为判断依据)

设 1 出现在 j 处,1 ~ j - 1 个数一定对应 2 ~ j。这 2 ~ j 的出栈顺序有 f[j - 1] 种(这 f[j - 1] 种中以 2 为界,但不用考虑,因为在之前算的时候是以 1 为界的)

j + 1 ~ i 上的数也一定是 j + 1 ~ j,情况有 f[i - j]种,理由同上
公式:

f[1] = 1;
// i >= 0;

公式

例7. 出栈序列
题目

n个数,n-1个乘号
类似上题,本次考虑的是乘号使用的先后,不多记录。

例8. 凸多边形划分
题目
例子
状态:f[n] 表示凸 n 边形的拆分方案总数。
由题目中的要求可知一个凸 n 边形的任意一条边都必然是一个三角形的一条边,边 P1Pn 也不例外,再根据“不在同一直线上的三点可以确定一个三角形”,只要在 P2,P3,……,Pn-1 点中找一个点 Pk(1 < k < n),与 P1、Pn共同构成一个三角形的三个顶点,就将n边形分成了三个不相交的部分(如图),我们分别称之为区域 ①、区域 ②、区域 ③,其中区域 ③ 必定是一个三角形,区域 ① 是一个凸 k 边形,区域 ② 是一个凸 n - k + 1 边形,区域 ① 的拆分方案总数是 f[k],区域 ② 的拆分方案数为 f[n - k + 1],故包含 △P1PkPn 的 n 边形的拆分方案数为 f[k] * f[n - k + 1] 种,而 Pk 可以是 P2,P3,……,Pn-1种任一点,根据加法原理,得以下递推关系式:
上面的图形解释

// f[2] = 1;
// i > 2 时:

1

作者:Rotch
日期:2020-10-06
修改:2020-10-06
[2020-10-06]:加入例题 8 凸多边形划分

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值