蓝桥杯软件类考点3:搜索_蓝桥杯考搜索吗

print(f'低洼地一共有{result}个')

![](https://img-blog.csdnimg.cn/direct/a3352c5a15e6486693d8ee2ac45ae16c.png)


#### 2、迷宫问题——DFS解法与BFS解法


问题:


给定一个二维迷宫,其中 0 表示通路,1 表示墙壁。起点为 (0, 0),终点为 (3,2),求从起点到终点的最短路径。


maze = [  
     [0, 0, 1, 0],  
     [0, 0, 0, 0],  
     [0, 0, 1, 0],  
     [0, 1, 0, 0],  
     [0, 0, 0, 1]  
 ]


#####  1、DFS栈的解法


DFS 通常不是最优选择,因为它可能会首先探索一个路径直到底部,然后回溯并探索另一路径,这可能导致找到的路径并非最短。通常,广度优先搜索 (BFS) 更适合解决这类最短路径问题。



def shortest_path_dfs(maze, start, end):
if not maze or not maze[0]:
return None

rows, cols = len(maze), len(maze[0])
visited = [[False] * cols for _ in range(rows)]  # 记录节点是否已访问
path = []  # 记录路径

# 定义方向数组,表示上、下、左、右四个方向
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]

# 定义DFS栈的解法
def dfs_stack():
    stack = [(start, [start])]  # 元组的第一个元素是位置,第二个元素是到达该位置的路径
    visited[start[0]][start[1]] = True

    while stack:
        (x, y), current_path = stack.pop()

        if (x, y) == end:
            return current_path

        for dx, dy in directions:
            nx, ny = x + dx, y + dy

            # 判断新位置是否在矩阵范围内,并且未访问过且是通路
            if 0 <= nx < rows and 0 <= ny < cols and not visited[nx][ny] and maze[nx][ny] == 0:
                stack.append(((nx, ny), current_path + [(nx, ny)]))
                visited[nx][ny] = True

    return []

path = dfs_stack()
return path

if name == ‘main’:
# 示例迷宫
maze = [
[0, 0, 1, 0],
[0, 0, 0, 0],
[0, 0, 1, 0],
[0, 1, 0, 0],
[0, 1, 0, 1],
[0, 0, 0, 1]
]

# 起点和终点
start = (0, 0)
end = (3, 2)

# 调用DFS栈的解法
result_path = shortest_path_dfs(maze, start, end)

# 输出路径
print("路径:", result_path)

##### 


![](https://img-blog.csdnimg.cn/direct/ba743a510e6c45a4bfd2e4980df7867d.png)


##### 2、DFS递归解法



def find_path_dfs(maze,start,end):
if not maze or not maze[0]:
return None

rows,cols = len(maze),len(maze[0])
visited = [[False] * cols for _ in range(rows)]
path = []

#定义方向组,表示上下左右
directions = [(-1,0),(1,0),(0,-1),(0,1)]

#定义DFS函数
def dfs(x,y):
    if x == end[0] and y == end[1]:
        path.append((x,y))
        return True

    visited[x][y] = True

    for dx,dy in directions:
        nx,ny = dx + x,dy + y

        # 判断新位置是否在矩阵范围内,并且未访问过且是通路
        if 0 <= nx < rows and 0 <= ny < cols and not visited[nx][ny] and maze[nx][ny] == 0:
            path.append((x,y))
            if dfs(nx,ny):
                return True
            path.pop() #删除最后一个元素,回溯

    return False

dfs(start[0],start[1])
return path

if name == ‘main’:
# 示例迷宫
maze = [
[0, 0, 1, 0],
[0, 0, 0, 0],
[0, 0, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 1]
]

# 起点和终点
start = (0, 0)
end = (3, 2)

# 调用DFS解法
result_path = find_path_dfs(maze, start, end)

# 输出路径
print("路径:", result_path)

##### 3、BFS队列解法



from collections import deque

def shortest_path_bfs(maze, start, end):
if not maze or not maze[0]:
return None

rows, cols = len(maze), len(maze[0])
visited = [[False] * cols for _ in range(rows)]  # 记录节点是否已访问

# 定义方向数组,表示上、下、左、右四个方向
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]

# 使用BFS队列的解法
queue = deque([(start, [])])  # 元组的第一个元素是位置,第二个元素是到达该位置的路径
visited[start[0]][start[1]] = True

while queue:
    (x, y), current_path = queue.popleft()

    if (x, y) == end:
        return current_path + [(x, y)]  # 找到终点,直接返回路径

    for dx, dy in directions:
        nx, ny = x + dx, y + dy

        # 判断新位置是否在矩阵范围内,并且未访问过且是通路
        if 0 <= nx < rows and 0 <= ny < cols and not visited[nx][ny] and maze[nx][ny] == 0:
            queue.append(((nx, ny), current_path + [(x, y)]))
            visited[nx][ny] = True

return None  # 没有找到路径,返回None

if name == ‘main’:
# 示例迷宫
maze = [
[0, 0, 1, 0],
[0, 0, 0, 0],
[0, 0, 1, 0],
[0, 1, 0, 0],
[0, 1, 0, 1],
[0, 0, 0, 1]
]

# 起点和终点
start = (0, 0)
end = (3, 2)

# 调用BFS解法
result_path = shortest_path_bfs(maze, start, end)

# 输出路径
print("路径:", result_path)


![](https://img-blog.csdnimg.cn/direct/f83d0b5500fe4f5eb5fbcedf407ed12e.png)


#### 3、数独游戏—剪枝


数独是一种逻辑游戏,要求在9×9的网格中填入数字1到9,使得每行、每列和每个3×3的小九宫格中都包含1到9的所有数字,而且不重复。求解下列数独。


    [5, 3, 0, 0, 7, 0, 0, 0, 0],  
     [6, 0, 0, 1, 9, 5, 0, 0, 0],  
     [0, 9, 8, 0, 0, 0, 0, 6, 0],  
     [8, 0, 0, 0, 6, 0, 0, 0, 3],  
     [4, 0, 0, 8, 0, 3, 0, 0, 1],  
     [7, 0, 0, 0, 2, 0, 0, 0, 6],  
     [0, 6, 0, 0, 0, 0, 2, 8, 0],  
     [0, 0, 0, 4, 1, 9, 0, 0, 5],  
     [0, 0, 0, 0, 8, 0, 0, 7, 9]


这是一个典型的搜索与剪枝问题,可以用深度优先搜索(DFS)算法来解决,这个程序使用深度优先搜索算法,通过递归填充数独中的数字,同时进行剪枝,最终得到解答。



‘’’
在递归算法中,return False 通常表示当前的尝试未成功,需要进行回溯操作。回溯是一种算法思想,它涉及
到返回到先前的状态,撤销之前所做的一些操作,然后尝试其他可能的选择。

在解数独的例子中,当在某个位置尝试填充数字时,如果发现当前的填充方式无法满足数独规则,就会执行
return False。这时,程序会回溯到上一层递归,继续尝试其他数字或回到更上一层递归。
‘’’

判断是否有重复数字

def is_valid(board,row,col,num):
# 检查行中是否有重复数字
if num in board[row]:
return False

# 检查列中是否有重复数字
if num in [board[i][col] for i in range(9)]:
    return False

# 检查3*3九宫格中是否有重复数字
start_row,start_col = 3 * (row // 3),3 * (col // 3)
for i in range(3):
    for j in range(3):
        if board[start_row+i][start_col+j] == num:
            return False

return True

def solve_sudu(board):
for row in range(9):
for col in range(9):
if board[row][col] == 0: # 未填数字位置
for num in range(1,10):
if is_valid(board,row,col,num):
board[row][col] = num
if solve_sudu(board): # 递归调用
return True # 所有的空格都填满,有解,退出返回结果
board[row][col] = 0 # 回溯
return False # 所有的数字都尝试过了,无解,回归到上一层递归if solve_sudu(board):

return True # 所有的空格都填满,有解

if name == ‘main’:
# 示例数独
sudoku_board = [
[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]
]

solve_sudu(sudoku_board)

# 输出解答
for row in sudoku_board:
    print(row)

可以多调试一下了解算法思想,特别是结合return Flase的回溯思想


![](https://img-blog.csdnimg.cn/direct/b2830ab98fc84e2aae7f443f310af904.png)


#### 4、单词接龙—双向BFS


给定两个单词(beginWord和endWord)和一个字典,找到从beginWord到endWord 的最短转换序列的长度。转换需遵循如下规律;  
 1.每次转换只能改变一个字母。  
 2.转换过程中的中间单词必须是字典中的单词。


说明:  
 如果不存在这样的转换序列,返回0。·所有单词具有相同的长度。  
 所有单词只由小写字母组成。字典中不存在重复的单词。  
 你可以假设beginWord和endWord是非空的,且二者不相同。


如题:


beginWord = "hit"  
 endWord = "cog"  
 wordList = ["hot", "dot", "dog", "lot", "log", "cog"]


求最短转换路径长度。



from collections import defaultdict,deque

def ladderLength(beginWord,endWord,wordList):
if endWord not in wordList and not beginWord and not endWord and not wordList:
return 0

# 构建通用状态字典,用于存储中间状态对应的单词列表
# word_dict={*ot': ['hot', 'dot', lot'], 'h*t': ['hot'], 'ho*: ['hot'], 'd*t': ['dot'],......
word_dict = defaultdict(list) # 构建一个默认value为list的字典
for word in wordList:
    for i in range(len(word)):
        word_dict[word[:i] + '*' + word[i+1:]].append(word)

# 双向BFS队列和访问集合
begin_queue = deque([(beginWord,1)]) # deque([('hit',1)])
end_queue = deque([(endWord,1)])
begin_visited = set([beginWord]) # {'hit'}
end_visited = set([endWord])

while begin_queue and end_queue:
    # 从起点开始扩展
    current_word,level = begin_queue.popleft() # current_word:'hit',level: 1
    for i in range(len(current_word)):
        intermediate_word = current_word[:i] + '*' + current_word[i+1:] # intermediate_word: '*it'
        for next_word in word_dict[intermediate_word]:
            if next_word in end_visited:
                return level + end_queue[-1][1] # 相遇,返回总层数
            if next_word not in end_visited:
                begin_queue.append((next_word,level + 1))
                begin_visited.add(next_word)

    # 从终点开始扩展
    current_word, level = end_queue.popleft()
    for i in range(len(current_word)):
        intermediate_word = current_word[:i] + '*' + current_word[i + 1:]
        for next_word in word_dict[intermediate_word]:
            if next_word in begin_visited:
                return level + begin_queue[-1][1]  # 相遇,返回总层级
            if next_word not in end_visited:
                end_queue.append((next_word, level + 1))
                end_visited.add(next_word)

return 0 # 无法找到转画序列

if name == ‘main’:
# 示例
beginWord = “hit”
endWord = “cog”
wordList = [“hot”, “dot”, “dog”, “lot”, “log”, “cog”]

result = ladderLength(beginWord, endWord, wordList)
print("最短转换序列长度:", result)

![](https://img-blog.csdnimg.cn/direct/da41f01bf07348e69b9e4f58afc2e01e.png)


#### 5、斐波那契数列—记忆化搜索


斐波那契数列中的每个数字都是前两个数字之和,即F(n) = F(n-1) + F(n-2),其中 F(0) = 0,


F(1) = 1。计算斐波那契数列的第 10 项。



记忆化搜索的斐波那契数列计算

def fibonacci(n, memo={}):
# 如果已经计算过该值,直接返回
if n in memo:
return memo[n]

# 斐波那契数列的基本情形
if n == 0:
    return 0
elif n == 1:
    return 1

# 计算并保存结果
result = fibonacci(n-1, memo) + fibonacci(n-2, memo)
memo[n] = result
return result

if name == ‘main’:
# 计算斐波那契数列的第 10 项
result = fibonacci(10)
print(“斐波那契数列第 10 项:”, result)


#### 6、八数码—迭代加深搜索


        一个经典的使用迭代加深搜索的例子是在八数码问题中找到最短路径。八数码问题是一个经典的拼图问题,目标是将一个3x3的九宫格中的数字从初始状态调整为目标状态。在每一步中,只允许交换空格与相邻数字的位置。求解下述八数码的最短路径。


![](https://img-blog.csdnimg.cn/direct/2c65061046714a64b2cae65a1e1b4ec5.png)



‘’’
初始状态
2 3
1 8 4
7 6 5
目标状态
1 2 3
8 4
7 6 5

‘’’

def iterative_deepening_search(start_state, target_state, max_depth):
for depth in range(1, max_depth + 1):
result = depth_limited_search(start_state, target_state, depth)
if result is not None:
return result

return None

def depth_limited_search(current_state, target_state, depth, current_depth=0, path=[]):
if current_depth == depth:
return None

if current_state == target_state:
    return path + [current_state]

for neighbor_state in get_neighbors(current_state):
    if neighbor_state not in path:
        result = depth_limited_search(neighbor_state, target_state, depth, current_depth + 1, path + [current_state])
        if result is not None:
            return result

return None

def get_neighbors(state):
# 根据八数码问题定义获取当前状态的相邻状态
neighbors = []
zero_index = state.index(0)
row, col = zero_index // 3, zero_index % 3

# 上下左右移动空格
for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
    new_row, new_col = row + dr, col + dc
    if 0 <= new_row < 3 and 0 <= new_col < 3:
        new_index = new_row * 3 + new_col
        new_state = list(state)
        new_state[zero_index], new_state[new_index] = new_state[new_index], new_state[zero_index]
        neighbors.append(tuple(new_state))

return neighbors

if name == ‘main’:
# 示例:解决八数码问题
start_state = (2, 3, 1, 8, 0, 4, 7, 6, 5) # 初始状态
target_state = (1, 2, 3, 8, 0, 4, 7, 6, 5) # 目标状态
max_depth_limit = 30 # 设置最大深度限制

result_path = iterative_deepening_search(start_state, target_state, max_depth_limit)

if result_path is not None:
    print("找到最短路径:")
    for state in result_path:
        print(state[:3])
        print(state[3:6])
        print(state[6:])
        print()
else:
    print("未找到最短路径")

![](https://img-blog.csdnimg.cn/direct/bf39caaa973e4df095d9d757f545eada.png)![](https://img-blog.csdnimg.cn/direct/bb0fb1291b154156bc896d3d0c6b0149.png)![](https://img-blog.csdnimg.cn/direct/38544baf4ee74dc5b769e425a6995e03.png)![](https://img-blog.csdnimg.cn/direct/3fdb684b0fbe486497f0b9d5bde3e43d.png)![](https://img-blog.csdnimg.cn/direct/1584ce203aa04658b17dfec03bc5d9c0.png)


#### 7、八数码—启发式搜索



‘’’
初始状态
2 3
1 8 4
7 6 5
目标状态
1 2 3
8 4
7 6 5
‘’’

from queue import PriorityQueue

def heuristic(state, target):
distance = 0
for i in range(3):
for j in range(3):
value = state[i][j]
if value != 0:
try:
target_row, target_col = divmod(target.index(value), 3)
except ValueError:
continue
distance += abs(i - target_row) + abs(j - target_col)
return distance

def print_move(state):
for row in state:
print(row)
print()

def a_star_search(initial_state, target_state):
frontier = PriorityQueue()
frontier.put((0, initial_state, []))

explored = set()

while not frontier.empty():
    _, current_state, path = frontier.get()

    if current_state == target_state:
        return path + [(current_state, "Goal")]

    if current_state in explored:
        continue

    explored.add(current_state)

    for neighbor_state, move in get_neighbors(current_state):
        if neighbor_state not in explored:
            new_path = path + [(current_state, move)]
            cost = len(new_path) + heuristic(neighbor_state, target_state)
            frontier.put((cost, neighbor_state, new_path))

return None

def get_neighbors(state):
neighbors = []
zero_row, zero_col = find_zero_position(state)

for dr, dc, move in [(0, 1, "Right"), (0, -1, "Left"), (1, 0, "Down"), (-1, 0, "Up")]:
    new_row, new_col = zero_row + dr, zero_col + dc
    if 0 <= new_row < 3 and 0 <= new_col < 3:
        new_state = list(map(list, state))
        new_state[zero_row][zero_col], new_state[new_row][new_col] = new_state[new_row][new_col], 0
        neighbors.append((tuple(map(tuple, new_state)), move))

return neighbors

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Linux运维工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Linux运维知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip1024b (备注Linux运维获取)
img

最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

资料预览

给大家整理的视频资料:

给大家整理的电子书资料:

如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Linux运维知识点,真正体系化!**

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip1024b (备注Linux运维获取)
[外链图片转存中…(img-sSFo606T-1712923816947)]

最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

资料预览

给大家整理的视频资料:

[外链图片转存中…(img-YU98yv2Z-1712923816947)]

给大家整理的电子书资料:

[外链图片转存中…(img-KTmBwhjw-1712923816948)]

如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-HhWC2uiR-1712923816948)]

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值