【python】回形取数——DFS算法

我知道这道题应该用BFS,我喜欢用DFS(狗头)

刚学会DFS,浅试一下

先来看题目

这道题一看就是需要用到搜索,至于是BFS还是DFS呢?因为只求一条路,所以就是BFS。但是呢,鄙人不会,就用DFS来做了。废话不多说,直接上代码。

import copy
m, n = map(int,input().split())
vis = [[False]*n for i in range(m)]
vec = []
for i in range(m):
    vec.append(list(map(int, input().split())))
dir = ((1, 0),(0, 1),(-1, 0),(0, -1))
stack = []
res=[]
def dfs(x, y):
    global res
    if x < 0 or x >= m or y < 0 or y >= n:
        return False
    if len(stack) == (m*n):
        if not res:
            res=copy.deepcopy(stack)
        return True
    if vis[x][y] == True:
        return False

    for i in range(4):
        xx, yy = x + dir[i][0], y + dir[i][1]
        if vis[x][y] == False:
            vis[x][y] = True
            stack.append(vec[x][y])
            dfs(xx, yy)
            vis[x][y] = False
            stack.pop()
dfs(0, 0)
for i in res:
    print(i,end=" ")

下面将按部分进行解释

m, n = map(int,input().split())
vis = [[False]*n for i in range(m)]
vec = []
for i in range(m):
    vec.append(list(map(int, input().split())))
stack = []
res=[]

这里是对题目中数据进行输入

m是行,n是列,vec是题目中的二维表,vis表示对路径进行记录,若走过就是True,没有走过就是

False。

stack和res是鄙人不会BFS所以用来模拟BFS的。

dir = ((1, 0),(0, 1),(-1, 0),(0, -1))

这一行代码是为了转向用的。这里要注意两点:第一,因为走过的会被记录,所以不用担心方向会乱跑,按照题目中所说的一开始向下,后来不断向左,那就是下、右、上、左,四个方向进行遍历就好了。第二,上下左右和我们坐标中理解的是不一样的。比方说(1,0)表示(x,y)中(x+1,y),索引中向下去一个元素,看下图:

(0,0)

(1,0)

import copy
def dfs(x, y):
    global res
    if x < 0 or x >= m or y < 0 or y >= n:
        return False
    if len(stack) == (m*n):
        if not res:
            res=copy.deepcopy(stack)
        return True
    if vis[x][y] == True:
        return False

    for i in range(4):
        xx, yy = x + dir[i][0], y + dir[i][1]
        if vis[x][y] == False:
            vis[x][y] = True
            stack.append(vec[x][y])
            dfs(xx, yy)
            vis[x][y] = False
            stack.pop()

接下来就是鄙人的DFS了,因为是第一次写出来深搜,所以允许鄙人再得瑟一下,哈哈哈

我感觉深搜其实和递归的模板差不多,都是定义函数、判断条件、进行递归。唯一不同的是深搜多了一个剪枝环节。

上面判断条件只有一点需要提一下,就是res赋值那里。如果直接进行复制,那是浅拷贝,会随着stack的变化而变化。而dfs会有很多种解,我只想要第一种,也就是模拟bfs。这时我不想让res有值之后再发生变化,所以需要:1.深拷贝,导入copy函数。2.判断条件,有值就不要再变了。

下面循环部分,(xx,yy)为下一个坐标,将此处坐标标记之后就开始dfs下一个坐标位置,之后不断递归,递归之后还原,正是需要还原才可以进行下一步,所以在还原的时候会对此处坐标再次读入进去,因此需要pop一下,以防出现重复的数字。

最后来看结果:

3 3
1 2 3
4 5 6
7 8 9
结果1 4 7 8 9 6 3 2 5
3 2
1 2
3 4
5 6
结果1 3 5 6 4 2

最后的最后,给大家提醒一下,这道题如果用搜索的话最多可以得20分,因为这道题用搜索是错的,看下面案例:

3 5
8470 6334 6506 9172 5727
1481 9364 6968 4470 5705
8151 3287 6830 9961 491
结果8470 1481 8151 3287 6830 9961 491 5705 5727 9172 4470 6968 6506 6334 9364

因为他不一定说直接每次按照上面的拐弯方法走就没有错,当列数越多就错的越离谱,因为测试样例太过于巧合,所以用搜索好像是对的。

但是为什么我结尾才告诉你呢(狡黠),嘿嘿,我想说我会DFS算法了,哈哈哈哈。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值