数据结构与算法(Python)– 回溯法(Backtracking algorithm)

数据结构与算法(Python)– 回溯法(Backtracking algorithm)


1、回溯法

回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。采用的是深度优先搜索。


2、迷宫

题目: 一个 N × M的二维数组 maze 表示一个迷宫,其中的1表示墙壁,0表示可以走,只能横着走或竖着走,不能斜着走,找出从左上角到右下角的最短路线。入口点为[0,0],既第一空格是可以走的。

回溯法:

# 走迷宫
def move(i, j):
    global path
    
    # 当前点变为1,表示已经走过,避免循环绕圈走不出去
    maze[i][j] = 1
    temp_path.append((i, j))
    # 如果已经走到了出口,即右下角,判断是不是最短路径
    if i == N - 1 and j == M - 1:
        if len(path) == 0 or len(temp_path) < len(path):
            path = []
            path.extend(temp_path)
	# 向下走
    if 0 <= i + 1 < N and not maze[i + 1][j]:
        move(i + 1, j)
    # 向右走
    if 0 <= j + 1 < M and not maze[i][j + 1]:
        move(i, j + 1)
    # 向上走
    if 0 <= i - 1 < N and not maze[i - 1][j]:
        move(i - 1, j)
    # 向左走
    if 0 <= j - 1 < M and not maze[i][j - 1]:
        move(i, j - 1)

	# 如果上下左右都走不通或者已经走到出口了,退回上一步,恢复现场
    temp_path.pop()
    maze[i][j] = 0


while True:
    try:
	    # 输入迷宫大小
        N, M = map(int, input().split())
        maze = []
        path = []
        temp_path = []
        # 输入迷宫地图
        for _ in range(N):
            maze.append(list(map(int, input().split())))

		# 走迷宫
        move(0, 0)

		# 打印路径
        for p in path:
            print('(' + str(p[0]) + ',' + str(p[1]) + ')')

    except:
        break

3、数独

题目: 根据9X9网格上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个3X3网格内的数字均含1-9,并且不重复。

回溯法:

# 检查该位置填该数字是否满足要求
def check(m,n,e):
    # 检查行
    if e in s[m]:
        return False
    # 检查列
    if e in s_T[n]:
        return False
    # 检查3X3网格
    x=m//3*3
    y=n//3*3
    for i in range(x,x+3):
        for j in range(y,y+3):
            if s[i][j]==e:
                return False
    return True

# 填数字
def move(k):
    if k==81:
        return 0
    # 从左到右,从上到下遍历每一格
    row,col=k//9,k%9
    # 如果是该格为空
    if s[row][col]=='0':
        # 从1~9依次尝试
        for e in num:
            # 如果该数满足要求,该格填上该数
            if check(row,col,e):
                s[row][col]=e
                s_T[col][row]=e
                # 移到下一格。如果下一格不管填什么都不满足要求,恢复现场
                if move(k+1):
                    s[row][col]='0'
                    s_T[col][row]='0'
                else:
                    return 0
        # 如果1~9都不满足,返回1
        return 1
    else:
        if move(k+1):
            return 1

while True:
    try:
        # 输入
        s=[input().split() for i in range(9)]
        s_T=[[s[i][j] for i in range(9)] for j in range(9)]
        num=['1','2','3','4','5','6','7','8','9']
        # 填数字
        move(0)
        # 打印
        for i in range(9):
            print(' '.join(s[i]))
    except:
        break

GOOD LUCK!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值