本节我们要讲解的算法是深度优先搜索(DFS)。顾名思义,广度优先搜索和深度优先搜索的区别在于,深度优先搜索是一条路走到底,再继续寻找下一条路;而广度优先搜索则是试图探寻每一步可能的路径。
按照惯例,我们先来看一道板子题:
-
题目背景
给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
-
题目描述
无。
-
输入格式
第一行N、M和T,N为行,M为列,T为障碍总数。
第二行起点坐标SX,SY,终点坐标FX,FY。
接下来T行,每行为障碍点的坐标。
-
输出格式
给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。
-
解析
-
思路
思路大概就是,先创建一个地图,自己填障碍,然后从起点开始调用DFS函数。每当DFS函数遇到终止条件时记一次数。
-
代码
m,n,t = map(int,input().split())#输入m,n,t
ls=[[0 for j in range(m)] for i in range(n)]#创捷一个m行n列的空列表
dir = [[0,-1],[0,1],[1,0],[-1,0]]#方向数组四个方向
ans = 0#答案初始化为0
f_x,f_y,e_x,e_y = map(int,input().split())#输入初始坐标和结束坐标
for i in range(0,t):#障碍输入
x,y = map(int,input().split())
ls[x-1][y-1] = 1
def DFS(x,y):#DFS函数核心
if x>m-1 or y>n-1 or x<0 or y<0:#如果越界,返回
return
if ls[x][y] == 1:#如果为1,返回
return
if x == e_x - 1 and y == e_y - 1:#如果到终点,计数并返回
global ans
ans += 1
return
for i in range(0,4):#如果执行到这里,说明没有返回。那么这个点可以走,向它的四个方向继续遍历
ls[x][y] = 1#标记
DFS(x+dir[i][0],y+dir[i][1])#下一次
ls[x][y] = 0#回溯
DFS(f_x-1,f_y-1)#调用
print(ans)#输出答案
下面是习题时间~
八皇后
-
题目描述
一个如下的 6 ×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
上面的布局可以用序列 2 4 6 1 3 5来描述,第 i 个数字表示在第 i 行的相应位置有一个棋子,如下:
行号 1 2 3 4 5 6
列号 2 4 6 1 3 5
这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前3个解。最后一行是解的总个数。 -
输入格式
一行一个正整数 n,表示棋盘是 n×n 大小的。
-
输出格式
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
-
思路
BFS函数按行递归,使用两个列表低复杂度的标记每一个结点所在行和斜行,统计到达底部且可行的次数。
-
代码
n = int(input())
ans = 0
mark_y = []
mark_xie = [0 for i in range(n * 10)]
mark_xie_other = [0 for i in range(n * 10)]
def DFS(m):
for i in range(n):
Judge = True
if i in mark_y:#如果标记了列,不行
Judge = False
if mark_xie[n-i+m]:#如果标记了斜,不行
Judge = False
if mark_xie_other[m+i]:
Judge = False
if i == n-1 and not Judge: #如果到n-1了(本行全都走完了),还走不了,就得返回上一层了
return
if Judge:#如果可以标记
if m == n-1:#而且进行到最后一行了
global ans
ans += 1#那ans就可以++了。
else:#如果没到最后一行
mark_y.append(i)#标记列
mark_xie[n-i+m] = 1#标记斜
mark_xie_other[m+i] = 1#标记斜
DFS(m+1)#下一层搜索
#每当一个return运行结束后 进入此处
#如果到这里,说明下一行全不行了,需要返回上一行进行下一次循环
#所以列表回溯
mark_y.remove(i)#
mark_xie[n-i+m] = 0
mark_xie_other[i+m] = 0
DFS(0)
print(ans)
本文转载自本人的个人博客,www.fengjx.cn。