第三章 搜索

深度优先搜索与宽度优先搜索

定义

深度优先搜索(DFS)

  过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。

宽度优先搜索(BFS)

  不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。

深度优先 与 宽度优先 实现的本质

  • 深优的本质是递归,自己调用自己。

  • 宽优的本质是利用队列经行的搜索。

深度优先与宽度优先区别

  • 深优的话,占内存少,能找到最优解(一定条件下),但能很快找到接近解(优解),可能不必遍历所有分枝(也就是速度快)。时间复杂度高。
  • 宽优的话,占内存多,能找到最优解,必须遍历所有分枝。
  • 深度优先一般是解决连通性问题,而宽度优先一般是解决最短路径问题。

深度优先搜索

扑克牌问题

  假如有编号为1 、2、3 的3 张扑克牌和编号为1 、2 、3 的3 个盒子。现在需要将这3 张扑克牌分别放到3 个盒子里面,并且每个盒子有且只能放一张扑克牌。那么一共有多少种不同的放法呢?

图解如下:

代码如下:

    #include<stdio.h>
int a[10],book[10],n; void dfs(int step) { // step表示站在第step个箱子前
int i;
if (step == n+1) { // 成立表示此时所有纸牌都放入箱子中
for (i=1;i<=n;i++)
printf("%d",a[i]);
printf("\n"); return; // 返回最近一次调用dfs函数的地方
} for (i=1;i<=n;i++) {
if (book[i] == 0) {
a[step] = i;
book[i] = 1; // 表示纸牌已用过
dfs(step + 1); // 移步到下一个箱子
book[i] = 0; // 收回用过的纸牌
}
}
return;
} int main() {
scanf("%d",&n);
dfs(1); // 开始站在第一个箱子前
return 0;
}

求通往 flag 的最短路程

  下题先用深度优先搜索解题,再利用宽度优先搜索解题。

题目:

  一只探险队从某一起点出发,寻找某处的宝藏。他们现在有一张藏宝图,为了携带更少的物资,他们需要根据地图求得通向宝藏的最短路程。(注:地图上的黑点代表障碍,无法通过)

地图示例:

深度优先解法:

图解:

思路:

  利用递归调用一条路走到头,再换一条路。

代码:

    #include<stdio.h>
int n,m,p,q,min=9999999; // 迷宫大小为 n*m,终点坐标为(p,q),最少步为 min
int a[51][51],book[51][51]; // a代表迷宫 ,book为所过路径标记集
void fun(int x,int y,int step) {
int next[4][2] = {{0,1}, // 向右走一步(向 y 轴正半轴平移一个单位)
{1,0}, // 向下走一步(向 x 轴正半轴平移一个单位)
{0,-1},
{-1,0}};// 类似上述,分别向左、向上走一步
int tx,ty,k;
if (x == p && y == q) {
if (step < min)
min = step;
// printf("%d\n",step); // 可以利用这条语句进行测试接近解
return; // 返回之前一步
} for (k=0; k<=3; k++) {
tx = x + next[k][0];
ty = y + next[k][1]; if (tx<1 || tx>n || ty<1 || ty > m)
continue; if (a[tx][ty] == 0 && book[tx][ty] == 0) {
book[tx][ty]=1; // 标记这个点已经走过
fun(tx,ty,step+1); // 开始尝试下一个点
book[tx][ty]=0; // 尝试结束,取消标记
}
}
return;
} int main() {
void fun(int x,int y,int step);
int i, j, startx, starty;
scanf("%d %d",&n,&m); for (i=1; i<=n; i++) // 绘制迷宫,0 为该区域可通行,1 为不可通行
for (j=1; j<=m; j++)
scanf("%d",&a[i][j]);
// 读入起点与终点坐标
scanf("%d %d %d %d",&startx,&starty,&p,&q); // 起点坐标为:(startx,starty), 终点坐标为:(p,q) book[startx][starty]=1;
fun(startx,starty,0); printf("%d\n",min); return 0;
}

宽度优先解法:

图解:

思路:

  利用队列推进,不断深入。

代码:

    #include<stdio.h>
struct note { // 定义一个结构体
int x;
int y;
int f;
int s; // 步数
}; int main() {
struct note que[2501]; // 结构体数组 int a[51][51] = {0},book[51][51] = {0}; int next[4][2] = {{0,1},{0,-1},{1,0},{-1,0}}; // 方向依次右、左、下、上
int head,tail;
int i,j,k,n,m,startx,starty,p,q,tx,ty,flag; scanf("%d %d",&n,&m);
for(i=1; i<=n; i++)
for(j=1; j<=m; j++)
scanf("%d",&a[i][j]); // 输入地图
scanf("%d %d %d %d",&startx,&starty,&p,&q); // 初始化结构体数组
head = 1;
tail = 1;
que[tail].x = startx;
que[tail].y = starty;
que[tail].f = 0;
que[tail].s = 0;
tail++;
book[startx][starty] = 1; flag = 0; while(head < tail) {
for(k=0; k<=3; k++) {
tx=que[head].x+next[k][0];
ty=que[head].y+next[k][1]; if (tx<1 || tx>n || ty<1 || ty>m) // 判断是否在地图上
continue;
if (a[tx][ty] == 0 && book[tx][ty] == 0) { // 判断是否可通过
book[tx][ty] = 1;
que[tail].x = tx;
que[tail].y = ty;
que[tail].f = head;
que[tail].s = que[head].s+1; // 路程加一,注意对哪一个数值经行加一运算
tail++;
} if (tx == p && ty == q) { // 判断是否达到终点
flag = 1;
break; // 退出for循环
}
}
if(flag == 1)
break; // 退出while循环
head++;
} printf("%d",que[tail-1].s); // 注意代表路程的值为哪一个
return 0;
}

测试数据:

6 6  // 地图大小 n行 m列
0 0 0 1 0 0
0 0 1 0 0 1
1 0 0 0 0 0
0 0 0 0 1 0
0 0 1 1 0 0
0 0 0 0 0 1 // 0 为可通过,1 为障碍
1 1 5 5 // 前两个数为起点坐标,后两个为终点坐标 8 8
0 0 1 0 1 0 0 0
0 0 0 0 0 0 1 0
1 0 1 0 0 1 0 0
0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0
1 0 1 0 0 1 1 1
1 0 0 0 0 1 0 0
0 0 0 1 0 0 0 1
1 1 7 7 12 12
0 0 0 0 0 1 0 0 1 0 0 0
0 1 0 0 0 0 0 0 0 0 1 0
0 0 0 1 0 0 1 0 1 0 0 0
0 0 1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 1 0 0 0 1 0 0
0 0 0 0 1 0 0 0 1 0 0 0
1 0 1 0 0 1 0 0 0 0 1 0
0 0 0 0 0 0 0 1 0 1 0 0
1 0 0 1 0 1 0 1 0 0 0 1
0 0 1 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0 0 0
0 1 0 0 1 0 0 0 1 0 0 0
1 1 11 11

总结:

  在数据较多时,深度优先搜索可以快速得到接近解,宽度优先搜索可以快速得到优解。(在利用12*12地图时,非常明显)

  

附:诗

以梦为马(或名:祖国)

——海子

我要做远方的忠诚的儿子

和物质的短暂情人

和所有以梦为马的诗人一样

我不得不和烈士和小丑走在同一道路上

万人都要将火熄灭

我一人独将此火高高举起

此火为大 开花落英于神圣的祖国

和所有以梦为马的诗人一样

我借此火得度一生的茫茫黑夜

此火为大 祖国的语言和乱石投筑的梁山城寨

以梦为马的敦煌——那七月也会寒冷的骨骼

如雪白的柴和坚硬的条条白雪 横放在众神之山

和所有以梦为马的诗人一样

我投入此火 这三者是囚禁我的灯盏 吐出光辉

万人都要从我刀口走过

去建筑祖国的语言

我甘愿一切从头开始

和所有以梦为马的诗人一样

我也愿将牢底坐穿

众神创造物中只有我最易朽

带着不可抗拒的死亡的速度

只有粮食是我珍爱 我将她紧紧抱住

抱住她 在故乡生儿育女

和所有以梦为马的诗人一样

我也愿将自己埋葬在四周高高的山上守望平静的家园

面对大河我无限惭愧

我年华虚度 空有一身疲倦

和所有以梦为马的诗人一样

岁月易逝 一滴不剩 水滴中有一匹马儿一命归天

千年后如若我再生于祖国的河岸

千年后我再次拥有中国的稻田

和周天子的雪山 天马踢踏

和所有以梦为马的诗人一样

我选择永恒的事业

我的事业 就是要成为太阳的一生

他从古至今——"日"——他无比辉煌无比光明

和所有以梦为马的诗人一样

最后我被黄昏的众神抬入不朽的太阳

太阳是我的名字

太阳是我的一生

太阳的山顶埋葬 诗歌的尸体

——千年王国和我

骑着五千年凤凰和名字叫"马"的龙

——我必将失败

但诗歌本身和太阳必将胜利









我知道我拖了一更。。。。别打脸。。。

以上

和我一起从0学算法(C语言版)(四)的更多相关文章

  1. 和我一起从0学算法(C语言版)(一)

    第一章 排序 第一节 简化版桶排法 友情提示:此文章分享给所有小白,大牛请绕路! 生活中很多地方需要使用排序,价格的由低到高.距离的由远及近等,都是排序问题的体现.如果排序量较少,依靠个人能力很容易实 ...

  2. 和我一起从0学算法(C语言版)(三)

    第二章 暴力求解(枚举法) 第一节 小学奥数题-程序求解 观察下面的加法算式:       祥 瑞 生 辉   +   三 羊 献 瑞 -------------------    三 羊 生 瑞 气 ...

  3. 和我一起从0学算法(C语言版)(二)

    第一章 排序 第三节 快速排序 快速排序是最常用的排序方法.快排运用的递归方法很有意思.掌握了这种排序方法可以在将来学习递归时更快入门.只是快排的思路与之前的排序方法相比较为复杂,再加担心上我的表达能 ...

  4. 教孩子学编程 python语言版PDF高清完整版免费下载|百度云盘|Python入门

    百度云盘:教孩子学编程 python语言版PDF高清完整版免费下载 提取码:mnma 内容简介 本书属于no starch的经典系列之一,英文版在美国受到读者欢迎.本书全彩印刷,寓教于乐,易于学习:读 ...

  5. libnode 0.4.0 发布,C++ 语言版的 Node.js

    libnode 0.4.0 支持 Windows ,提升了性能,libuv 更新到 0.10.17 版本,libj 更新到 0.8.2 版本. libnode 是 C++ 语言版的 Node.js,和 ...

  6. 快速排序算法C语言版

    快速排序(Quicksort)是对冒泡排序的一种改进.  快速排序由C. A. R. Hoare在1962年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比 ...

  7. 数据结构1:数据结构与算法C语言版分析概述

    本节开始将带领大家系统地学习数据结构,作为一门计算机专业大二学生的必修课程,该课程面对的目标人群为初步具备基本编程能力和编程思想的程序员(大一接触了 C 语言或者 C++).通过系统地学习数据结构,可 ...

  8. 【Leetcode 做题学算法周刊】第四期

    首发于微信公众号<前端成长记>,写于 2019.11.21 背景 本文记录刷题过程中的整个思考过程,以供参考.主要内容涵盖: 题目分析设想 编写代码验证 查阅他人解法 思考总结 目录 67 ...

  9. 《数据结构与算法(C语言版)》严蔚敏 | 第五章 建立二叉树,并完成三/四种遍历算法

    PS:所有的代码示例使用的都是这个图 2019-10-29 利用p126的算法5.3建立二叉树,并完成三种遍历算法 中序 后序 先序 #include<iostream> #include ...

随机推荐

  1. ELK之 elasticsearch ES集群 head安装

    最近项目用到 jenkins  ELK  也在一次重新学习了一次  jenkins 不用说了 玩得就是  插件   +  base---shell ,  ELK  这几年最流得log收集平台,当然不止 ...

  2. jQuery原理系列-工具函数

    jquery源码中有很多精妙的实现,对于我们每天都在使用的东西,一定要知其原理,如果遇到不能使用jquery环境,也能自己封装原生的代码实现. 1.检测类型 众所周知typeof 不能用来检测数据,会 ...

  3. zoj 1483 划分类DP

    还是看了little_w大神写的才知道怎么写,看完发现自己题意也理解错了,里面有个neighboring,意思就是你指定任务的时候指定的是原序列中连续的一段 然后就是怎么DP了,新学了个很好的dp模型 ...

  4. 干货分享:如何搞定Essay Paragraph部分?

    想要写出一篇高质量的留学生作业,首先要从写好段落(paragraph)开始.那么今天就随小编一起来看看,如何写好Paragraph部分? 段落:在英文中我们俗称为paragraph,而一篇英文文章通常 ...

  5. 说说lock到底要锁谁?

    波安搬... http://www.cnblogs.com/wolf-sun/p/4209521.html ---------------------------------------------- ...

  6. Nginx php-fpm 分离搭建 (上) 未完

    最近又重新看了一遍   'nginx入门到精通'      抽点时间 出来搭几个Demo  会有更深体会: Nginx如何与Php-fpm结合 Nginx不只有处理http请求的功能,还能做反向代理. ...

  7. BZOJ 4888 [Tjoi2017]异或和

    题解:对每一位分别考虑贡献 先求前缀和 按照二进制减法分类讨论,求出最终这一位是1还是0 用树状数组维护 注意:树状数组对0这个位置单独考虑 #include<iostream> #inc ...

  8. Canvas基本定义

    Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0.今天我们主要要了解的是2D相关的 大部分2D使用的api都在android.g ...

  9. SpringBoot 系列教程之事务不生效的几种 case

    SpringBoot 系列教程之事务不生效的几种 case 前面几篇博文介绍了声明式事务@Transactional的使用姿势,只知道正确的使用姿势可能还不够,还得知道什么场景下不生效,避免采坑.本文 ...

  10. 干货分享:Essay Introduction的正确打开方式

    其实在学术essay写作过程中,很多留学生经常不知道如何写introduction,所以有些开头的模板句就出现了,比如,With the development of society/With the ...