Unverified Commit c4e0d07b authored by ir1d's avatar ir1d Committed by GitHub
Browse files

Merge pull request #412 from CBW2007/patch-9

Update
parents 47bc4e9f 186ff06f
Loading
Loading
Loading
Loading
+28 −5
Original line number Diff line number Diff line
# 递归

介绍分治之前,首先要弄清楚 [递归](https://zh.wikipedia.org/zh-hans/%E9%80%92%E5%BD%92) 这个概念。
介绍分治之前,首先要弄清楚递归这个概念。

递归是什么呢?举个简单的例子:从前有座山,山上有座庙,庙里有个老和尚,老和尚给小和尚讲故事,讲的什么故事呢?从前有座山,山上有座庙,庙里有个老和尚……

递归的基本思想是某个函数直接或者间接地调用自身,这样就把原问题的求解转换为许多性质相同但是规模更小的子问题。我们只需要关注如何把原问题划分成符合条件的子问题,而不需要去研究这个子问题是如何被解决的。

@@ -8,20 +10,41 @@

在用递归思想解题的时候,要考虑三个要素。

## 递归式
## 递归三要素

### 递归式

具体是如何将原问题划分为子问题?
如何将原问题划分为子问题?如何科学地进行递归?

## 递归出口
### 递归出口

终止的条件是什么?换言之,最小的子问题是怎么求解的。

出口可以不止一个。

## 界函数
### 界函数

我们用一个函数来表示问题规模变化,这个函数需要保证递归的条件是在像出口条件靠拢。

### 递归模板

```c++
int f(传入数值)
{
    if (终止条件)
        return 最小子问题解;
    return f(缩小规模);
}
```

## 递归优化

先来一道例题:[三连击](https://www.luogu.org/problemnew/show/P1028)

这道题朴素的递归写法只能得到 25 分,因为递归次数太多,所以超时。

怎么优化呢?详见 [搜索优化](/search/optimization)[记忆化搜索](https://oi-wiki.org/dp/memo/)

# 分治

分治是一种极为重要的思想。顾名思义,分而治之,就是把大问题化小,再各个击破的过程。
+27 −14
Original line number Diff line number Diff line
@@ -123,9 +123,7 @@ int main(){
#### 总结一下记忆化搜索是啥:

- 不依赖任何 **外部变量**

- 答案以返回值的形式存在, 而不能以参数的形式存在 (就是不能将 dfs 定义成 $dfs(pos ,tleft , nowans )$, 这里面的 nowans 不符合要求).

- 对于相同一组参数, dfs 返回值总是相同的

* * *
@@ -236,17 +234,13 @@ dp 状态很显然:
举例: 用常规 dp 写 "合并石子" 需要先枚举区间长度然后枚举起点, 但记忆化搜索直接枚举断点 (就是枚举当前区间由哪两个区间合并而成) 然后递归下去就行

- 边界情况非常好处理, 且能有效防止数组访问越界

- 有些 dp (如区间 dp) 用记忆化搜索写很简单但正常 dp 很难

- 记忆化搜索天生携带搜索天赋, 可以使用技能 "剪枝"!

缺点:

- 致命伤: 不能滚动数组!

- 有些优化比较难加

- 由于递归, 有时效率较低但不至于 TLE (状压 dp 除外)

* * *
@@ -254,7 +248,26 @@ dp 状态很显然:
## 5. 记忆化搜索的注意事项

- 千万别忘了加记忆化! (别笑, 认真的

- 边界条件要加在检查当前数组值是否为 - 1 前 (防止越界)

- 边界条件要加在检查当前数组值是否为非法数值 (防止越界)
- 数组不要开小了 (逃

## 6. 模板

```c++
int g[MAXN]
int f(传入数值)
{
    if (g[规模]!=无效数值)
        return g[规模];
    if (终止条件)
        return 最小子问题解;
    g[规模]=f(缩小规模);
    return g[规模];
}
int main()
{
    ...
    memset(g,无效数值,sizeof(g));
    ...
}
```
+1 −0
Original line number Diff line number Diff line
+2 −1
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ nav:
    - 基础部分简介: basic/index.md
    - 枚举: basic/enumerate.md
    - 模拟: basic/simulate.md
    - 分治: basic/divide-and-conquer.md
    - 递归&分治: basic/divide-and-conquer.md
    - 贪心: basic/greedy.md
    - 排序: basic/sort.md
    - 表达式求值: basic/expression.md
@@ -45,6 +45,7 @@ nav:
    - IDA*: search/idastar.md
    - 回溯法: search/backtracking.md
    - Dancing Links: search/dlx.md
    - 优化: search/optimization.md
  - 动态规划:
    - 动态规划部分简介: dp/index.md
    - 记忆化搜索: dp/memo.md