数据结构(三十一)

学习数据结构与算法过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。

—— 八数码难题 ——

1.题目描述

八数码问题也称为九宫问题。在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格,与空格相邻的棋子可以移到空格中。要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始状态转变成目标状态的移动棋子步数最少的移动步骤。

代码

使用算法:启发式搜索算法
使用广度搜索算法求解点击这里

python

import copy
import numpy as np

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)

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 get_distance(arr1, arr2):
    distance = []
    for i in arr1:
        for j in i:
            loc1 = get_loacl(arr1, j)
            loc2 = get_loacl(arr2, j)
            distance.append(abs(loc1[0] - loc2[0]) + abs(loc1[1] - loc2[1]))
    return sum(distance)


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

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

    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,
                          distance=self.deep + 1 + get_distance(self.state, goal_arr))
            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 = '2 8 3,1 6 4,7 0 5'
    goal = '1 2 3,8 0 4,7 6 5'
    initial_arr = string_to_ls(initial)
    goal_arr = string_to_ls(goal)
    initial_arr = state(initial_arr, deep=0, parent=None, distance=get_distance(initial_arr, goal_arr))
    open = [initial_arr]
    close = []
    limit = 19
    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)
            break
        else:
            if n.deep < limit:
                for i in n.chidren():
                    if i.state not in open_tb:
                        if i.state not in close_tb:
                            open.insert(0, i)
                            open.sort(key=lambda x: x.distance)
    else:
        print('无解')

    print('搜索步数为:',len(close) - 2)
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐