Checkio 8 puzzle(数字华容道)

#数字华容道#广度优先算法,bfs

3×3的数字华容道想必大家都玩过,利用python算法也可以实现华容道的快速回正

8-拼图

输入: 一个数字从 1 到 8 的矩阵,作为包含整数的列表列表。

输出: 空单元格的字符串路由。

例:

checkio([[123],
[468],
[750]]) == “ULDR”
1
2
3

使用方法: 此任务中概念最明显的用途在于创建一个机器人来解决幻灯片谜题; 然而,这个任务也是一种学习新事物的有趣方式,因为 n 谜题是涉及启发式算法建模的经典问题。

前提条件:
len(puzzle) == 3
all(len(row) == 3 for row in puzzle)

from collections import deque


def countInversion(puzzle, blankpos):
"""8 puzzle问题存在定理,即当面对N×N的puzzle,如果逆序对的个数的奇偶性恰好相反则有解,因此编写一个函数用来计算被扁平化后的puzzle存在多少组逆序对,来筛除不合法的情况"""
    inversion = 0
    puzzle.pop(blankpos)
    for i in range(len(puzzle)):
        for j in range(i+1, len(puzzle)):
            if puzzle[i] > puzzle[j]:
                inversion += 1
    puzzle.insert(blankpos, 0)
    return inversion


def checkio(puzzle):
"""此函数先将puzzle扁平化,然后创建一个访问集合用来存储父级puzzle,然后将路径,空格位置,以及子级puzzle打包。通过队列实现广度优先算法,遍历当前空格位置对应的父级puzzle存在的所有子级情况。设置一定的筛选条件,比如一维数组在二维空间的障碍,会导致某些移动不合法,因此可以在step步数上节省时间。同时对于计算的空格的下一个位置所组成的子级puzzle是否可解,当可解时,保存。"""
    directions = {
        "U": -3, "D": +3, "L": -1, "R": +1
    }
    puzzle = [item for sublist in puzzle for item in sublist]
    # 创造一个访问集合
    visited = set()
    # 创造一个队列,并将空格位置作为父级节点,加入
    queue = deque([(puzzle.index(0), tuple(puzzle), "")])
    while queue:
        vertex, puzzle, path = queue.popleft()
        if puzzle == (1, 2, 3, 4, 5, 6, 7, 8, 0):
            return path
        visited.add(puzzle)
        for dir, step in directions.items():
            if (vertex % 3 == 0 and step == -1) or (vertex % 3 == 2 and step == +1):
                continue  # 第一列和最后一列,不能左右移动
            if vertex < 3 and step == -3:
                continue  # 第一行,不能上移
            if vertex >= 6 and step == +3:
                continue  # 最后一行,不能下移
            next_pos = vertex+step
            test_puzzle = list(puzzle)
            test_puzzle[vertex], test_puzzle[next_pos] = test_puzzle[next_pos], test_puzzle[vertex]
            if countInversion(test_puzzle, next_pos) % 2 == 0:
                if tuple(test_puzzle) not in visited:
                    queue.append((next_pos, tuple(test_puzzle), path+dir))

    return None


checkio([[1, 2, 3],
         [4, 6, 8],
         [7, 5, 0]])

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值