Python深度优先解决八数码问题

宽度优先解决八数码问题基础上对节点类增加深度属性

import copy
import numpy as np
from datetime import datetime


# 字符串列表化
def string_to_ls(str):
    return [i.split(' ') for i in str.split(',')]


# 获取位置
def get_loacl(arr, target):
    # r, c = np.where(arr == target)
    # return r, c
    for i in arr:
        for j in i:
            if j == target:
                return arr.index(i), i.index(j)


# 获取可以和0交换位置的元素
def get_elements(arr):
    r, c = get_loacl(arr, '0')
    elements = []
    if r > 0:
        elements.append(arr[r - 1][c])  # 上面的元素
    if r < 2:
        elements.append(arr[r + 1][c])  # 下边的元素
    if c > 0:
        elements.append(arr[r][c - 1])  # 左面的元素
    if c < 2:
        elements.append(arr[r][c + 1])  # 右面的元素
    return elements


def get_child(arr, e):
    # 深拷贝与浅拷贝!!
    arr_new = copy.deepcopy(arr)
    r, c = get_loacl(arr_new, '0')
    r1, c1 = get_loacl(arr_new, e)
    arr_new[r][c], arr_new[r1][c1] = arr_new[r1][c1], arr_new[r][c]
    return arr_new


def is_goal(arr, goal):
    return arr == goal


class state:
    def __init__(self, state, deep, parent):
        # state是一个3x3的ls矩阵
        self.state = state
        self.deep = deep
        self.parent = parent

    def chidren(self):
        chidren = []
        for i in get_elements(self.state):
            child = state(state=get_child(self.state, i), deep=self.deep + 1, parent=self)
            chidren.append(child)
        return chidren


# 打印求解路径
def print_path(n):
    if n.parent == None:
        return
    else:
        print('↑')
        print(np.array(n.parent.state))
        print_path(n.parent)


if __name__ == '__main__':
    # initial = '0 1 3,4 2 5,7 8 6'
    # goal = '4 1 3,7 0 5,8 2 6'
    # initial = '0 7 8,2 5 4,3 6 1'
    # goal = '7 5 8,2 4 1,3 6 0'
    initial = '4 0 1,6 8 5,7 3 2'
    goal = '5 8 2,1 0 4,6 3 7'
    initial_arr = state(string_to_ls(initial), deep=0, parent=None)
    goal_arr = string_to_ls(goal)
    start = datetime.now()
    open = [initial_arr]
    close = []
    # limit = eval(input('请输入要搜索的深度:'))
    limit = 20
    while len(open) > 0:
        open_tb = [i.state for i in open]
        close_tb = [i.state for i in close]
        n = open.pop(0)
        close.append(n)
        if is_goal(n.state, goal_arr):
            print(np.array(n.state))
            print_path(n)
            print('求解过程如上')
            break
        else:
            if n.deep < limit:
                for i in n.chidren():
                    if i.state not in open_tb:
                        if i not in close_tb:
                            open.insert(0, i)
    else:
        print('该深度下无解')

    end = datetime.now()
    print('深度为{}下的搜索步数为:{}'.format(close[-1].deep, len(close) - 2))
    print('共耗时:', end - start)

### 回答1: 八数码问题是指在一个3x3的九宫格中,放置了1-8的数字和一个空格,要求通过移动数字,使得九宫格最终变为如下状态: 1 2 3 4 5 6 7 8 Python深度优先搜索算法可以用来解决八数码问题。具体步骤如下: 1. 定义状态表示:将九宫格状态表示为一个3x3的矩阵,其中空格用表示。 2. 定义状态扩展:对于当前状态,可以将空格向上、下、左、右四个方向移动,每次移动后得到一个新状态。 3. 定义状态判重:为了避免重复搜索,需要记录已经搜索过的状态。 4. 定义目标状态:目标状态即为九宫格最终状态。 5. 定义搜索过程:从初始状态开始,不断扩展状态,直到找到目标状态或者搜索完所有状态。 6. 定义搜索策略:深度优先搜索算法采用栈来保存状态,每次从栈顶取出一个状态进行扩展。 7. 定义搜索结束条件:当找到目标状态或者搜索完所有状态时,搜索结束。 通过以上步骤,可以使用Python深度优先搜索算法解决八数码问题。 ### 回答2: 八数码问题是一个经典的人工智能问题,也是一道很好的算法练习题目。深度优先搜索则是其中的一种解决方法,在Python中实现也非常简单。 八数码问题是指在一个3x3的棋盘上,放置有数字1-8的数字牌,以及一个空格(用0表示)。游戏的目标是通过交换数字牌位置,使得棋盘上的数字牌按照从左到右、从上到下的顺序排列,最终形成12345678,0的格子位于右下角。 深度优先搜索是一种常用的图遍历算法,它从初始状态开始,递归地深入每一个可能的分支,当到达目标状态或者无法继续搜索时,返回上一层进行回溯,尝试其他的可能分支。深度优先搜索的核心是回溯,递归回溯过程中存储节点的状态,以及搜索的深度和路径。 在Python中实现深度优先搜索的八数码问题需要三个关键部分:状态表示、深度优先搜索函数以及启发式函数。状态表示使用三维数组,表示当前棋盘上数字牌的位置状态。深度优先搜索函数通过递归的方式实现深度优先搜索,每次递归更新状态和深度,并根据启发式函数根据状态判断是否需要继续搜索。启发式函数用来估算当前状态距离目标状态的距离,即当前状态与目标状态的差异,以确定搜索策略。 深度优先搜索算法虽然在八数码问题中可以实现,但是该算法存在着一些问题,比如可能出现无限循环的情况,搜索效率达不到最优等问题。因此,实际应用中,我们需要结合其他算法和启发式函数来实现更高效的搜索。 ### 回答3: 八数码问题是一道经典的算法问题,也是深度优先搜索算法的经典实现案例之一。Python语言可以非常方便地实现这个问题,使用深度优先搜索算法解决八数码问题深度优先搜索算法是一种有向图遍历算法,它从一个起始节点开始,沿着一个方向遍历整个图,直到遍历结束或者发现目标节点。在八数码问题中,我们可以将每一个棋盘状态看作一个节点,然后通过深度优先搜索算法来遍历这个棋盘状态图,找到目标状态。 具体实现时,我们可以使用一个字典来表示每一个棋盘状态的信息。字典的键为棋盘状态,值为一个元组,元组的第一个元素表示该状态的父状态,第二个元素表示该状态是由父状态经过哪一个移动得到的。另外,我们还需要使用一个列表来记录已经访问过的状态,避免出现环路。 在每一次搜索中,我们首先判断当前状态是否为目标状态,如果是,则直接返回;如果不是,我们就对当前状态进行拓展,即尝试从当前状态进行一次移动,得到新的状态,并将新的状态加入到搜索队列和已访问状态列表中。然后我们继续对队列中的下一个状态进行搜索,直到队列为空或者搜索到目标状态为止。 值得注意的是,在搜索过程中,我们需要对状态进行判重处理,否则可能会导致出现环路,并且搜索效率也会受到影响。因此,我们应该在每次加入一个新的状态时,检查该状态是否已经出现在了已访问状态列表中,如果已经出现,则不应该再次加入该状态。 总之,通过深度优先搜索算法,我们可以方便地实现八数码问题的求解。这个问题实质上是在一个搜索空间中寻找一条从初始状态到目标状态的路径,因此可以使用深度优先搜索算法来实现。Python语言具有语法简洁,易于理解的优点,因此适合用来解决这个问题
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值