stripe-python 2022-03-11 22:14 采纳率: 100%
浏览 90
已结题

请问求解数字华容道有什么算法(语言-python)

最近在写一个求解数字华容道的程序,用BFS可以求解3x3,但是在往上就不行了
想到了一个分治,就是数字华容道中的降阶法,5x5转4x4再转3x3,但速度还是不行
请问求解数字华容道还有什么速度快的算法?

环境: python 3.8

BFS代码:

from collections import deque, defaultdict
from typing import List
from copy import deepcopy

TARGET = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, -1]
]  # 定义结果列表


def find_position(target: int, board: List[List[int]]):
    """
    寻找一个值在二维列表中的位置。

    :param target: 目标值
    :param board: 二维列表
    :return: 值在二维列表中的位置
    """
    for x, i in enumerate(board):  # 遍历board,时间复杂度O(n2)
        for y, j in enumerate(i):
            if j == target:
                return x, y
    raise ValueError


def find_next(state: str):
    """
    给定当前状态,返回可以由当前状态变换而成的状态。
    
    :param state: 当前状态字符串表示
    :return: 可以由当前状态变换而成的状态list,保证长度为2-4
    """
    board = eval(state)  # 转列表
    res = []
    x, y = find_position(-1, board)
    for nx, ny in ((0, 1), (0, -1), (-1, 0), (1, 0)):  # 遍历四个方向
        tx, ty = nx + x, ny + y
        if 0 <= tx < 3 and 0 <= ty < 3:  # 在范围内
            temp = deepcopy(board)  # 二维列表深拷贝一份
            temp[x][y], temp[tx][ty] = temp[tx][ty], temp[x][y]   # 移动方向上的数字
            res.append(str(temp))
    return res


def get_parent(board: List[List[int]]):
    """
    给定一个盘面,返回运算后的父级关系哈希表。
    
    :param board: 初始盘面,二维列表
    :return: 父级关系哈希表
    """
    parent = defaultdict(str)
    state = str(board)  # 字符串可以哈希
    visited = {state}   # 遍历过的状态
    q = deque()
    q.append(state)
    parent[state] = 'None'
    while q:   # bfs穷举求解
        state = q.popleft()
        # print(state)
        if state == str(TARGET):
            return parent
        for nxt in find_next(state):
            if nxt not in visited:
                q.append(nxt)   # 放到待处理队列中
                visited.add(nxt)
                parent[nxt] = state   # 记录关系
    return parent


def get_list(ans: List[str]):
    """
    对比每个状态,求上下状态中移动方向。
    
    :param ans: 状态列表
    :return: 移动方向列表
    """
    res = []
    for index, item in enumerate(ans):
        if index == 0:
            continue
        item = eval(item)
        last = eval(ans[index - 1])   # 上一个状态
        lx, ly = find_position(-1, last)
        # 上一个状态中空缺位置在这个状态中的数字即为移动的数字
        move = item[lx][ly]
        nx, ny = find_position(move, last)   # 上一个状态中移动数字的位置
        if lx - nx == 1:
            res.append('down')
        elif lx - nx == -1:
            res.append('up')
        elif ly - ny == 1:
            res.append('right')
        else:
            res.append('left')
        # print(last, item, res)
    return res


def find_answer(parent: defaultdict, start: str):
    """
    给定父级关系哈希表和初始盘面,求移动方向。
    
    :param parent: 父级关系哈希表
    :param start: 初始盘面的字符状态
    :return: 数字移动方向
    """
    ans = [str(TARGET)]   # 状态列表
    father = parent[str(TARGET)]
    while father != start:   # 遍历整个树,逆推还原解题过程
        ans.append(father)
        father = parent[father]
    ans.append(str(start))
    ans.reverse()
    return get_list(ans)


def get_result(board: List[List[int]]):
    """
    主函数,给定初始盘面,求数字移动方向。
    
    :param board: 初始盘面
    :return: 数字移动方向
    """
    parent = get_parent(board)
    ans = find_answer(parent, str(board))
    return ans


if __name__ == '__main__':
    print(get_result(
        [[3, 6, 5], [2, 4, 1], [8, 7, -1]]
    ))
  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 3月19日
    • 创建了问题 3月11日

    悬赏问题

    • ¥30 YOLO检测微调结果p为1
    • ¥20 求快手直播间榜单匿名采集ID用户名简单能学会的
    • ¥15 DS18B20内部ADC模数转换器
    • ¥15 做个有关计算的小程序
    • ¥15 MPI读取tif文件无法正常给各进程分配路径
    • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
    • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
    • ¥15 setInterval 页面闪烁,怎么解决
    • ¥15 如何让企业微信机器人实现消息汇总整合
    • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题