Commit 52a558d2 authored by ir1d's avatar ir1d
Browse files

Merge remote-tracking branch '24OI/master'

parents dafc77b6 72a746d4
Loading
Loading
Loading
Loading
+8 −11
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@
# 欢迎来到 **OI Wiki**!

[![Travis](https://img.shields.io/travis/OI-WIKI/OI-wiki.svg?style=flat-square)](https://travis-ci.org/OI-wiki/OI-wiki)
[![Progress](https://img.shields.io/badge/Progress-88%25-brightgreen.svg?style=flat-square)](https://github.com/OI-wiki/OI-wiki)
[![Uptime Robot Status](https://img.shields.io/uptimerobot/status/m781254113-3e3bac467c64fc99eafd383e.svg?style=flat-square)](https://status.oi-wiki.org/)
[![Telegram](https://img.shields.io/badge/OI--wiki-join%20Telegram%20chat-brightgreen.svg?style=flat-square)](https://t.me/OIwiki)
[![QQ](https://img.shields.io/badge/OI--wiki-join%20QQ%20group-brightgreen.svg?style=flat-square)](https://jq.qq.com/?_wv=1027&k=5EfkM6K)
@@ -20,15 +19,9 @@

**OI Wiki** 致力于成为一个免费开放且持续更新的知识整合站点,大家可以在这里获取关于 **编程竞赛 (competitive programming)** 有趣又实用的知识,我们为大家准备了竞赛中的基础知识、常见题型、解题思路以及常用工具等内容,帮助大家更快速深入地学习编程竞赛。

目前,**OI Wiki** 正在完善各大方向的基础知识,以便于初学者更好地学习
目前,**OI Wiki** 的内容还有很多不完善的地方,知识点覆盖不够全面,存在一些低质量页面需要修改。**OI Wiki** 团队以及参与贡献的小伙伴们正在积极完善这些内容

**OI Wiki** 基于 **OI**,却不会局限于 **OI****OI Wiki** 会努力完善以下内容:

- 应用在 **ICPC** 竞赛中的进阶知识
- 竞赛中出现的优质题目
- 与面试、实际应用相结合的经验

关于上述待完善内容,请参见 **OI Wiki** 中的 [Projects](https://github.com/OI-wiki/OI-wiki/projects),详细列举了正在做的事情以及待做事项。
关于上述待完善内容,请参见 **OI Wiki**[Issues](https://github.com/OI-wiki/OI-wiki/issues) 以及 [迭代计划](https://github.com/OI-wiki/OI-wiki/labels/%E8%BF%AD%E4%BB%A3%E8%AE%A1%E5%88%92%20%2F%20Iteration%20Plan)

与此同时, **OI Wiki** 源于社区,提倡 **知识自由**,在未来也绝不会商业化,将始终保持独立自由的性质。

@@ -104,6 +97,7 @@ python2 -m SimpleHTTPServer
## 如何参与完善 OI Wiki

我们非常欢迎你为 **OI Wiki** 编写内容,将自己的所学所得与大家分享。

具体的贡献方式在 [如何参与](https://oi-wiki.org/intro/htc/)

* * *
@@ -141,6 +135,9 @@ python2 -m SimpleHTTPServer

特别感谢 [24OI](https://github.com/24OI) 的朋友们的大力支持!

<img src='https://i.loli.net/2018/12/07/5c0a6e4c31b30.png' alt='QVQNetWork' width=233>
<!-- <img src='https://i.loli.net/2018/12/07/5c0a6e4c31b30.png' alt='QVQNetWork' width=233> 
鸣谢 QVQNetwork 赞助的服务器。 -->

感谢 北大算协 和 Hulu 的支持!

鸣谢 QVQNetwork 赞助的服务器。
![](https://assets.pcmag.com/media/images/560767-hulu.png?width=333&height=245)
+2 −1
Original line number Diff line number Diff line
@@ -28,7 +28,8 @@ if (cur) {

document.getElementsByTagName("html")[0].lang = "zh-Hans"; // change language to `zh-Hans` for Han.js.

var url = document.getElementsByClassName('page_edit_url')[0].href.split('docs')[1]
var url = document.getElementsByClassName('page_edit_url')[0].href.split('?ref=')[1]
// var url = document.getElementsByClassName('page_edit_url')[0].href.split('docs')[1]
// var url = document.URL.replace(/http\S+\.org\//gi, '').replace(/#\S+$/gi, '').slice(0, -1);
var script = document.createElement('script');
function foo(response) {
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ $$
C++ 代码:

```cpp
// 假设数组的大小是n+1,冒泡排序从数组下标1开始
void bubble_sort(int *a, int n) {
  bool flag = true;
  while (flag) {
+1 −1
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ $$

#### Problem

 [BZOJ4971:\[Lydsy1708 月赛\]记忆中的背包](https://www.lydsy.com/JudgeOnline/problem.php?id=4971) 
 [Lydsy1708 月赛记忆中的背包](https://www.lydsy.com/JudgeOnline/problem.php?id=4971) 

#### Solution

+8 −8
Original line number Diff line number Diff line
author: fudonglai
author: fudonglai, AngelKitty

首先简单阐述一下递归,分治算法,动态规划,贪心算法这几个东西的区别和联系,心里有个印象就好。

@@ -27,11 +27,11 @@ int func(传入数值) {
}
```

其实仔细想想, **递归运用最成功的是什么?我认为是数学归纳法。** 我们高中都学过数学归纳法,使用场景大概是:我们推不出来某个求和公式,但是我们试了几个比较小的数,似乎发现了一点规律,然后了一个公式,看起来应该是正确答案。但是数学是很严谨的,你哪怕穷举了一万个数都是正确的,但是第一万零一个数正确吗?这就要数学归纳法发挥神威了,可以假设我们的这个公式在第 k 个数时成立,如果证明在第 k + 1 时也成立,那么我们的这个公式就是正确的。
其实仔细想想, **递归运用最成功的是什么?我认为是数学归纳法。** 我们高中都学过数学归纳法,使用场景大概是:我们推不出来某个求和公式,但是我们试了几个比较小的数,似乎发现了一点规律,然后猜想了一个公式,看起来应该是正确答案。但是数学是很严谨的,你哪怕穷举了一万个数都是正确的,但是第一万零一个数正确吗?这就要数学归纳法发挥神威了,可以假设我们猜想的这个公式在第 k 个数时成立,如果证明在第 k + 1 时也成立,那么我们猜想的这个公式就是正确的。

那么数学归纳法和递归有什么联系?我们刚才说了,递归代码必须要有结束条件,如果没有的话就会进入无穷无尽的自我调用,直到内存耗尽。而数学证明的难度在于,你可以尝试有穷种情况,但是难以将你的结论延伸到无穷大。这里就可以看出联系了——无穷。

递归代码的精髓在于调用自去解决规模更小的子问题,直到到达结束条件;而数学归纳法之所以有用,就在于不断把我们的猜测向上加一,扩大结论的规模,没有结束条件,从而把结论延伸到无穷无尽,也就完成了猜测正确性的证明。
递归代码的精髓在于调用自去解决规模更小的子问题,直到到达结束条件;而数学归纳法之所以有用,就在于不断把我们的猜测向上加一,扩大结论的规模,没有结束条件,从而把结论延伸到无穷无尽,也就完成了猜测正确性的证明。

### 为什么要写递归

@@ -137,13 +137,13 @@ int count(TreeNode node, int sum) {

题目看起来很复杂吧,不过代码却极其简洁,这就是递归的魅力。我来简单总结这个问题的 **解决过程**

首先明确,递归求解树的问题必然是要遍历整棵树的,所以 **二叉树的遍历框架** (分别对左右孩子递归调用函数本身)必然要出现在主函数 pathSum 中。那么对于每个节点,们应该干什么呢?们应该看看,自己和脚底下的小弟们包含多少条符合条件的路径。好了,这道题就结束了。
首先明确,递归求解树的问题必然是要遍历整棵树的,所以 **二叉树的遍历框架** (分别对左右孩子递归调用函数本身)必然要出现在主函数 pathSum 中。那么对于每个节点,们应该干什么呢?们应该看看,自己和脚底下的小弟们包含多少条符合条件的路径。好了,这道题就结束了。

按照前面说的技巧,根据刚才的分析来定义清楚每个递归函数应该做的事:

PathSum 函数:给一个节点和一个目标值,返回以这个节点为根的树中,和为目标值的路径总数。
PathSum 函数:给一个节点和一个目标值,返回以这个节点为根的树中,和为目标值的路径总数。

count 函数:给一个节点和一个目标值,返回以这个节点为根的树中,能凑出几个以该节点为路径开头,和为目标值的路径总数。
count 函数:给一个节点和一个目标值,返回以这个节点为根的树中,能凑出几个以该节点为路径开头,和为目标值的路径总数。

```cpp
/* 有了以上铺垫,详细注释一下代码 */
@@ -167,7 +167,7 @@ int count(TreeNode node, int sum) {
}
```

还是那句话, **明白每个函数能做的事,并相信们能够完成。** 
还是那句话, **明白每个函数能做的事,并相信们能够完成。** 

总结下,PathSum 函数提供的二叉树遍历框架,在遍历中对每个节点调用 count 函数,看出先序遍历了吗(这道题什么序都是一样的);count 函数也是一个二叉树遍历,用于寻找以该节点开头的目标值路径。好好体会吧!

@@ -200,6 +200,6 @@ void merge_sort(一个数组) {
}
```

好了,这个算法也就这样了,完全没有任何难度。记住之前说的,相信函数的能力,传给半个数组,那么这半个数组就已经被排好了。而且你会发现这不就是个二叉树遍历模板吗?为什么是后序遍历?因为我们分治算法的套路是 **分解 -> 解决(触底)-> 合并(回溯)** 啊,先左右分解,再处理合并,回溯就是在退栈,就相当于后序遍历了。至于 `merge` 函数,参考两个有序链表的合并,简直一模一样。
好了,这个算法也就这样了,完全没有任何难度。记住之前说的,相信函数的能力,传给半个数组,那么这半个数组就已经被排好了。而且你会发现这不就是个二叉树遍历模板吗?为什么是后序遍历?因为我们分治算法的套路是 **分解 -> 解决(触底)-> 合并(回溯)** 啊,先左右分解,再处理合并,回溯就是在退栈,就相当于后序遍历了。至于 `merge` 函数,参考两个有序链表的合并,简直一模一样。

LeetCode 上有分治算法的专项练习, [点这里去做题](https://leetcode.com/tag/divide-and-conquer/) 
Loading