这篇文章将会将一个数据结构与算法中一个很经典很重要的概念——深度优先搜索(Depth-First-Search:DFS)。。。。。。。。。(你他喵不是在标题里说了吗?)

好吧,DFS的精髓我其实也还没有弄的特别懂,估计得多用用才能理解更深吧。

!!!敲黑板!!!DFS的关键是递归,递归是真好用!!!


深度优先搜索(DFS)

什么是DFS呢,秉着能动手就绝不吵吵的原则,直接给出网上大神的博文链接:http://www.cnblogs.com/skywang12345/p/3711483.html

好吧,其实这种链接你自己都能百度到的。我就放这里做个参考,我的主要目的还是要讲一下骑士周游问题。

骑士周游问题

骑士周游问题的主要内容是什么呢?不是废话,直接上网址:http://blog.fishc.com/2554.html,这个页面对DFS问题说明的非常清楚。作者是小甲鱼大神,我在B站看的就是他的数据结构课程,不时的开个车差点闪了我的腰。

特喵的,不是说好的不说废话吗?(我错了,好吧)

好吧,直接上代码:

import datetime
from enum import Enum class Size(Enum):
X = 8 start = datetime.datetime.now()
chess = [[0 for i in range(Size.X.value)]for j in range(Size.X.value)] def nextXY(x, y, position):
global chess
if position==0 and x-2>=0 and y-1>=0 and chess[x-2][y-1]==0:
return [1, x-2, y-1]
elif position==1 and x-2>=0 and y+1<=Size.X.value-1 and chess[x-2][y+1]==0:
return [1, x-2, y+1]
elif position==2 and x-1>=0 and y-2>=0 and chess[x-1][y-2]==0:
return [1, x-1, y-2]
elif position==3 and x-1>=0 and y+2<=Size.X.value-1 and chess[x-1][y+2]==0:
return [1, x-1, y+2]
elif position==4 and x+1<=Size.X.value-1 and y-2>=0 and chess[x+1][y-2]==0:
return [1, x+1, y-2]
elif position==5 and x+1<=Size.X.value-1 and y+2<=Size.X.value-1 and chess[x+1][y+2]==0:
return [1, x+1, y+2]
elif position==6 and x+2<=Size.X.value-1 and y-1>=0 and chess[x+2][y-1]==0:
return [1, x+2, y-1]
elif position==7 and x+2<=Size.X.value-1 and y+1<=Size.X.value-1 and chess[x+2][y+1]==0:
return [1, x+2, y+1]
else:
return [0, x, y] def TravelChessBoard(x, y, tag):
global chess
chess[x][y] = tag
if tag == Size.X.value**2:
for i in chess:
print(i)
return "OK"
f = 0
for i in range(8):
flag = nextXY(x, y, i)
if flag[0]:
statues = TravelChessBoard(flag[1], flag[2], tag+1)
if statues=="OK":
return "OK"
f += 1
else:
f += 1
if f == 8:
chess[x][y] = 0 print(TravelChessBoard(2, 0, 1))
print(datetime.datetime.now() - start)

整单代码一共可以分为三个部分:变量准备部分,位置判断部分,循环递归部分。

1.变量准备部分:

    • 定义了一个size枚举类,这是用于实现C语言中宏定义的功能特意定义的,当然你用别的方法也行,主要就是为了方便改变棋盘的规模。
    • 定义了一个棋盘变量,是一个二维矩阵,全部元素初始化为0。也就是问题中的棋盘

2.位置判断部分:

    • 函数有三个参数,分别是坐标x, y和位置position, 这个位置position先来解释一下,如下图[1]所示,在国际象棋中,按照马的走法(马走日)对于任何一个位置,马能走的地方一共有8个位置,每一个位置对应的坐标变换不一样,这里的position对应的就是8种坐标变换方式。(x, y)就是马当前所处的位置坐标
    • 返回的参数为一个列表,列表中包含三个元素,第一个元素表示8个位置是否存在满足条件的下一个位置,若存在,则第二、三两个元素返回新位置的坐标,若不存在,返回原始坐标
    • 判断的条件主要就是同时满足两个方面:坐标不能出界,坐标对应的位置未曾走过(位置上的值为0),两者都满足即存在满足条件的下一个位置
  • 循环递归函数:
 def TravelChessBoard(x, y, tag):
global chess
chess[x][y] = tag
if tag == Size.X.value**2:
for i in chess:
print(i)
return "OK"
f = 0
for i in range(8):
flag = nextXY(x, y, i)
if flag[0]:
statues = TravelChessBoard(flag[1], flag[2], tag+1)
if statues=="OK":
return "OK"
f += 1
else:
f += 1
if f == 8:
chess[x][y] = 0
    • 传进来的参数为当前马所在的位置(x, y),以及当前走的是第几步(tag的值)
    • 第行,chess[x][y] = tag, 另当前位置的值等于当前的步数,未到达的地方则为0,以此判断一个位置是否到达过
    • 第4-6行,如果步数等于棋盘的总格数(这里默认为方盘),则将棋盘打印出来,返回”OK“状态,告诉上一层递归已经寻找到解了,无需再作其它搜索了
    • 第行,定义一个过程变量f = 0, 作用稍后会讲到
    • 第-17行,对马的当前位置的下8个位置进行遍历,对于每一个位置,如果存在下个符合条件的位置则进入递归,将符合条件的下一个位置作为当前位置传入递归函数中,步数加1。对8个位置遍历,每次出现一个不符合条件的位置则f的值就加一。
    • 第18-19行,当8个位置全部遍历完,没有一个符合条件的位置,那么此时f = 8,说明当前位置是不符合条件,那么就将当前位置的值重新置为0。
    • 再说第12-15行,当深层的遍历找不到合适的位置时,递归会退回到前一层,这说明前一层的当前位置也不符合条件,那么f的值就必须加1,然后继续遍历前一层的下一个位置,以此类推。
    • 最后再说13-14行,当已经找到并打印出符合条件的路径后,程序饭后”OK“状态,此时程序的递归就会从最后一层不断往前一层返回,为了加快程序结束的速度,就不继续进行剩下的遍历,每一层递归都直接返回可以了。如果不直接返回的话,程序会将所有的情况都遍历完再返回,这样时间就会非常非常非常长。YOU CAN HAVE A TRY !!!

到此这个程序也差不多讲完了,我觉得只要理解递归了,这个程序应该不难理解。


连续几天都在用递归,对递归的运用也越来越熟练,确实非常好用,真诚地希望这篇文章对你有帮助。

愿各位学业有成!!!

[1] 图拷贝自http://blog.fishc.com/2554.html,感谢鱼C工作室。

Python----DFS---骑士周游问题的更多相关文章

  1. 【数据结构与算法Python版学习笔记】图——骑士周游问题 深度优先搜索

    骑士周游问题 概念 在一个国际象棋棋盘上, 一个棋子"马"(骑士) , 按照"马走日"的规则, 从一个格子出发, 要走遍所有棋盘格恰好一次.把一个这样的走棋序列 ...

  2. 骑士周游问题跳马问题C#实现(附带WPF工程代码)

    骑士周游问题,也叫跳马问题. 问题描述: 将马随机放在国际象棋的8×8棋盘的某个方格中,马按走棋规则进行移动.要求每个方格只进入一次,走遍棋盘上全部64个方格. 代码要求: 1,可以任意选定马在棋盘上 ...

  3. poj 2488 A Knight's Journey 【骑士周游 dfs + 记忆路径】

    题目地址:http://poj.org/problem?id=2488 Sample Input 3 1 1 2 3 4 3 Sample Output Scenario #1: A1 Scenari ...

  4. 图论 --- 骑士周游问题,DFS

    A Knight's Journey   Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 28630   Accepted: ...

  5. 骑士周游问题 --- 递归解法 --- java代码

    骑士游历: 定义了向量的数组M,行数组X,列数组Y, 棋盘plane,计数器count,走动步数step 需要注意的是,递归函数的进入前的验证,原先的想法是传入来时的方向参数,可是这样的想法被实践否定 ...

  6. leetcode算法题121-123 --78 --python版本

    给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 实例输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必须在原数组上操作,不能 ...

  7. 【数据结构与算法Python版学习笔记】目录索引

    引言 算法分析 基本数据结构 概览 栈 stack 队列 Queue 双端队列 Deque 列表 List,链表实现 递归(Recursion) 定义及应用:分形树.谢尔宾斯基三角.汉诺塔.迷宫 优化 ...

  8. day53-马踏棋盘

    马踏棋盘 1.算法优化的意义 算法是程序的灵魂,为什么有些程序可以在海量数据计算时,依旧保持高速计算? 编程中算法很多,比如八大排序算法(冒泡.选择.插入.快排.归并.希尔.基数.堆排序).查找算法. ...

  9. BNU 26579 Andrew the Ant 【蚂蚁】

    链接: http://www.bnuoj.com/bnuoj/problem_show.php?pid=26579 http://www.bnuoj.com/bnuoj/contest_show.ph ...

随机推荐

  1. Python3基础(八) 模块

    在程序中定义函数可以实现代码重用.但当你的代码逐渐变得庞大时,你可能想要把它分割成几个文件,以便能够更简单地维护.同时,你希望在一个文件中写的代码能够被其他文件所重用,这时我们应该使用模块(modul ...

  2. 【oracle11g,18】存储结构:暂时表,手工条带化,表/索引迁移表空间,删除表,外部表

    一. 暂时表 暂时表放在暂时表空间,不生成redo,仅仅有undo. 在暂时表中能够创建索引.视图及触发器,还能够使用"Export and Import(导出和导入)"或&quo ...

  3. Andriod实现刮刮卡的效果

    思想: 将一个View设计成多层,内层(包含中奖信息)和外层(用于刮奖),外层的图层用Canvas与一个Bitmap关联,用这个关联的Bitmap来处理手势的滑动.类似于刮奖的动作. 使用paint. ...

  4. LeetCode 234. Palindrome Linked List (回文链表)

    Given a singly linked list, determine if it is a palindrome. Follow up:Could you do it in O(n) time ...

  5. 【WIP】Bootstrap modal

    创建: 2017/09/28   更新: 2017/10/14 标题加上[WIP]

  6. mysql大数据的分表

    在实际业务运作中,我们经常遇到一个表中数据量过大的问题,这样的话,问题就来了.如何将一个表中的数据均衡的放到多个表中? 我的建议是,新建一个表,但是只有一个自增的id字段,将其作为分表的依据.有大数据 ...

  7. kindeditor上传文件的使用

    在线富文本编辑器kindeditor配置(.Net Framework 3.5)   下载地址:http://kindeditor.net/down.php 解压放在项目要目录下, 在Bin目录下添加 ...

  8. 北大zhw大神bzoj1756代码

    #include <cmath> #include <cstdio> #include <cstdlib> #include <iostream> #i ...

  9. distpicker三级联动,动态改变省市信息

    一.引入3个js文件 <script type="text/javascript" src="js/distpicker.data.js">< ...

  10. zb的生日-------搜索 和 动态规划

    简单的贪心算法 : http://love-oriented.com/pack/P01.html  说实话 我是喜欢 动态规划的.......但是省赛迫在眉睫 , 只好先 学 搜索了  ,  赶紧   ...