搜索基础讲解

版权声明:博主的博客不值钱随便转载但要注明出处 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.练习

相关题目已经布置,都属于基础性题目,请大家认真完成,切勿抄袭!

http://codevs.cn/problem/2806/

http://acm.nuc.edu.cn/OJ/problem/show/1983

猜你喜欢

转载自blog.csdn.net/easylovecsdn/article/details/83657356