问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

蓝桥杯备赛:DFS算法详解与实战

创作时间:
作者:
@小白创作中心

蓝桥杯备赛:DFS算法详解与实战

引用
CSDN
1.
https://blog.csdn.net/weixin_71409897/article/details/137163298

坚持坚持!(解题步骤部分借鉴大佬们的代码,如有侵权请联系删除)

一、DFS例题

试题链接: 路径之谜

问题描述:小明冒充X星球的骑士,进入了一个奇怪的城堡。城堡里什么也没有,只是方形石头铺成的地面。假设城堡地面是n×n个方格。如图所示。

按习俗,骑士要从西北角走到东南角。可以横向或纵向移动,但不能斜着走,也不能跳跃。每走到一个新方格,就要向正北方和正西方各射一箭。(城堡的西墙和北墙内各有n个靶子)

同一个方格只允许经过一次。但不必走完所有的方格。如果只给出靶子上箭的数目,你能推断出骑士的行走路线吗?有时是可以的,比如上图中的例子。本题的要求就是已知箭靶数字,求骑士的行走路径(测试数据保证路径唯一)

输入格式
第一行一个整数N(0<N<20),表示地面有N×N个方格。
第二行N个整数,空格分开,表示北边的箭靶上的数字(自西向东)
第三行N个整数,空格分开,表示西边的箭靶上的数字(自北向南)
输出格式
一行若干个整数,表示骑士路径。
为了方便表示,我们约定每个小格子用一个数字代表,从西北角开始编号:0,1,2,3,……。
比如图中的方块编号为

输入样例
4
2 4 3 4
4 3 3 3

输出样例
0 4 5 1 2 3 7 11 10 9 13 14 15

问题分析

首先我们的初始位置为(1,1),我们设置了两个列表dx,dy可以让其进行上下移动,并且每到一个新位置,就会把其北边和南边的箭拔掉。

check函数帮助我们判断该点是否到了出口,若到了出口判断墙上是否还有箭。若有,则回溯;若没有,则直接输出所有点的位置。(每个点的值可以用n*(x-1)+y-1表示)

pd函数帮助我们判断能否走到该点,即判断该点是否走过、横纵坐标有没跑出格子外、该点的北面和西面墙上还有没箭。

dfs函数对于每一个点,先check,再往上下左右走,并进行pd,若可行,则进行拔箭,存储该点(为最后print服务),记录走过该点。然后对其下一个位置进行dfs,若下一个位置各种路径都走不出去,则又返回到该点的位置,那我们需要进行场景复原,把墙上的箭插回去等,并继续遍历,朝其他方向走。

sys.exit()实现在print之后整个程序结束运行

代码示例

import os
import sys

def dfs(i, j):
    global key, no, we
    if pd(i, j):
        return
    else:
        for _ in range(4):
            ii = i + he[_]
            jj = j + sh[_]
            if check(ii, jj):
                key[ii][jj] = 1
                we[ii] -= 1
                no[jj] -= 1
                ls.append(ii * n + jj)
                dfs(ii, jj)
                key[ii][jj] = 0
                we[ii] += 1
                no[jj] += 1
                del ls[-1]

def check(ii, jj):
    global key, no, we
    if ii < 0 or jj < 0 or ii >= n or jj >= n:
        return False
    elif key[ii][jj] == 1:
        return False
    elif we[ii] == 0 or no[jj] == 0:
        return False
    else:
        return True

def pd(i, j):
    global key, no, we, n
    if i != n - 1 or j != n - 1:
        return False
    elif max(no) != 0 or max(we) != 0:
        return False
    else:
        for _ in ls:
            print(_, end=" ")
        sys.exit()

if __name__ == "__main__":
    n = int(input())
    no = [int(_) for _ in input().split()]
    we = [int(_) for _ in input().split()]
    no[0] -= 1
    we[0] -= 1
    key = [[0] * n for _ in range(n)]
    key[0][0] = 1
    he = [-1, 0, 1, 0]
    sh = [0, -1, 0, 1]
    ls = [0]
    dfs(0, 0)
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号