版权声明:博主的博客不值钱随便转载但要注明出处 https://blog.csdn.net/easylovecsdn/article/details/83657356
前言:搜索可以解决什么样的问题?
(1) 可行解的求解(例如 POJ - 3278:中文题意 https://vjudge.net/problem/POJ-3278#author=hnshhslsh)
(2) 二维图形的移动搜索(http://codevs.cn/problem/1215/)
等
1.什么是搜索?
(1) 搜索算法的解决思路是尽可能的将问题的所有的可能性列出,再在其中去寻求我们需要的结果。
(2) 这里我们主要介绍深度优先搜索(dfs)和广度优先搜索(bfs).
2.递归函数
<Question> 用递归的形式求取斐波那契数列第n项
图中明显进行了fib(1) —— fib(5) 的所有运算,不难看出有重复运算,因此效率还不够高。
#include <stdio.h>
int fib(int n)
{
if (n == 1 || n == 2) return 1; //先写出递归出口
return fib(n - 1) + fib(n - 2); //调用自身进行递归运算
}
int main()
{
printf("%d\n", fib(5)); //输出fib的第5项
return 0;
}
引入数组记录结果提高执行效率
#include <stdio.h>
#include <cstring>
int a[105];
/*fib效率改进*/
int fib(int n)
{
if (n == 1 || n == 2) return a[n]; //先写出递归出口
if (!a[n]) a[n] = fib(n - 1) + fib(n - 2);
return a[n]; //调用自身进行递归运算
}
int main()
{
memset(a, 0 ,sizeof(a));
a[1] = 1;
a[2] = 1;
printf("%d\n", fib(5)); //输出fib的第5项
return 0;
}
!关于斐波那契数列的坑点:第X项会爆int型的数据范围。
<怎么写递归函数>
(1) 明确递归出口
(2) 头脑中建立“递归树”模型,思考递归过程中如何将可能性罗列出来
(3) 大量练习
<递归练手>
http://codevs.cn/problem/1842/
3.回溯(重点)
回溯是DFS(Depth-First-Search)深度优先搜索的关键思想,掌握了回溯的思想就等同于掌握了DFS基础
<Question> 利用DFS进行全排列生成
http://codevs.cn/problem/1294/
题解:(让大家体会dfs思想,严禁粘贴代码)
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 15;
int a[maxn];
int n;
bool vis[maxn]; //该元素是否使用
void print()
{
for (int i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n");
}
void dfs(int val, int inx) //参数的含义表示将val放到下标索引为inx的位置上
{
a[inx] = val;
if (inx == n-1) {
print();
return ;
}
for (int i = 1; i <= n; i++) {
if (vis[i] == false) { //先判断i是不是被选中了
vis[i] = true; //纳入
dfs(i, inx+1);
vis[i] = false; //不纳入
}
}
}
int main()
{
scanf("%d", &n);
memset(vis, false, sizeof(vis));
for (int i = 1; i <= n; i++) {
vis[i] = true; //将元素i选入集合
dfs(i, 0);
vis[i] = false; //元素i不选入集合
}
return 0;
}
本题坑点:体会cout与printf的输出效率
4.体会DFS
<Question> 经典DFS问题,走迷宫
http://codevs.cn/problem/1215/
5.练习
相关题目已经布置,都属于基础性题目,请大家认真完成,切勿抄袭!