8 Puzzle

  • 问题
  • 思路
  • 代码
  • 结果

问题

这一次的编程作业是完成一个类似于“华容道”的游戏——8 puzzle:

给定一个 N×NN\times NN×N 的网格图,其中有一个网格被挖空,其余网格标记为 1,2,3,⋯,N×N−11,2,3,\cdots, N\times N-11,2,3,⋯,N×N−1。每次可以将被挖空的网格与相邻被标记数字的网格交换,目标是移至成 1,2,3,4⋯,N×N−11,2,3,4\cdots, N\times N-11,2,3,4⋯,N×N−1 依次排列,最后一个网格被挖空的情况。

原题链接

思路

首先定义一个数据类型 Board,储存 N×NN\times NN×N 的二维数组,用 0 表示被挖空的网格,找出其相邻的 Board。定义每一个 Board 与目标 Board 之间的 Hamming 距离和 Manhattan 距离。定义一个新的数据类型 State,用来储存 Board、移动步数、前一个State。

接下来可以利用 A* search algorithm 来解决这个问题:先把初始 State 加入优先队列,然后每次删去 Manhattan 最小的 State,加入其相邻的 State(如果该 State 不曾在优先队列中出现过),直至删去的 State 的 Manhattan 距离为 0。

注意到,任意给定一个初始状态,未必能达到目标状态。可以利用逆序数来判断:当且仅当原初始状态在一维数组下是偶排列时,该问题是可行的。

代码

# -*- coding: utf-8 -*-
"""
Created on Thu Dec 10 16:34:21 2020@author: zxw
"""
import numpy as np
import timeN = 3
goal = [i+1 for i in range(N*N)]
goal[N*N-1] = 0class Board:
#construct a board from an N-by-N array of tilesdef __init__(self, tiles):self.Array = np.array(tiles).reshape(N,N)
# return number of blocks out of placedef hamming(self):temp = N*N-1-sum(sum(self.Array == Board(goal).Array))if sum(sum(np.argwhere(self.Array == 0))) == 2*(N-1):            return temp+1else:return temp# return sum of Manhattan distances between blocks and goaldef manhattan(self):manhattan_i = []for i in range(N*N-1):manhattan_i.append(sum(sum(abs(np.argwhere(self.Array == i+1)-np.argwhere(Board(goal).Array == i+1)))))return sum(manhattan_i) # does this board equal ydef equals(self,y):return sum(sum(self.Array == y.Array)) == N*N# return an Iterable of all neighboring board positionsdef neighbours(self):location = np.argwhere(self.Array==0)[0]x = location[0]y = location[1]neighbors = []copies= [self.Array.copy() for i in range(4)]if x != 0:copies[0][x][y] = self.Array[x-1][y]copies[0][x-1][y] = 0neighbors.append(Board(copies[0]))if x != N-1:copies[1][x][y] = self.Array[x+1][y]copies[1][x+1][y] = 0neighbors.append(Board(copies[1]))if y != 0:copies[2][x][y] = self.Array[x][y-1]copies[2][x][y-1] = 0neighbors.append(Board(copies[2]))if y != N-1:copies[3][x][y] = self.Array[x][y+1]copies[3][x][y+1] = 0        neighbors.append(Board(copies[3]))return neighbors
# return a string representation of the boarddef toString(self):for i in range(N):for j in range(N):if self.Array[i][j] != 0:print(str(self.Array[i][j])+'  ',end="")else:print('   ',end="")print('\n')class State:def __init__(self,board,move,pre):self.Board = boardself.Move = moveself.Pre = pre    class MinPQ:def __init__(self):self.states = []self.states.append(0)self.n = 0def insert(self, newstate):self.n = self.n+1self.states.append(newstate)self.swim(self.n)def delMin(self):Min = self.states[1]self.exch(1, self.n)self.n = self.n-1del self.states[self.n + 1]self.sink(1)return Mindef swim(self,k):if k <= 1:returnwhile (k > 1) & (self.states[int(k/2)].Board.manhattan() > self.states[k].Board.manhattan()):self.exch(int(k/2) , k)k = int(k/2)if k <= 1:returndef sink(self,k):while (2*k <= self.n):j = 2*kif (j < self.n):if (self.states[j].Board.manhattan() > self.states[j+1].Board.manhattan()):j = j+1if not self.states[k].Board.manhattan() > self.states[j].Board.manhattan():breakself.exch(k, j)k = jdef exch(self,i,j):t = self.states[i]self.states[i] = self.states[j]self.states[j] = tclass Solver:def __init__(self, board):self.initial_state = State(board,0,None)self.pq = MinPQ()self.pq.insert(self.initial_state)if self.isSolvable(): while self.pq.states[1].Board.manhattan() != 0:dequeue = self.pq.delMin()for neighbor in dequeue.Board.neighbours():if dequeue.Pre is None:self.pq.insert(State(neighbor,dequeue.Move+1,dequeue))elif not neighbor.equals(dequeue.Pre.Board):Flag = 1for state in self.pq.states:if state == 0:passelif state.Board.equals(neighbor):Flag = 0if Flag == 1:    self.pq.insert(State(neighbor,dequeue.Move+1,dequeue))else:print("It is not solvable!")def isSolvable(self):List = list(self.initial_state.Board.Array.reshape(1,N*N)[0])k = 0for i in range(1,N*N-1):for j in range(0,i):if List[j] > List[i]:k = k+1return k%2 == 0def moves(self):return self.pq.states[1].Movedef toString(self):Move_list = []Move_list.append(self.pq.states[1])while Move_list[-1].Pre != None:Move_list.append(Move_list[-1].Pre)Move_list.reverse()for each in Move_list:each.Board.toString()print('\n')if __name__ == '__main__':a = [0,1,3,4,2,5,7,8,6]test = Board(a)solve = Solver(test)solve.toString()b = [1,2,3,4,5,6,8,7,0]test = Board(b)solve = Solver(test)

结果


注:该算法仍有一个小问题:对于某些较复杂的初识状态(比如[2,1,3,4,5,6,8,7,0]),运行时间过久。不知可否能进一步改进?

普林斯顿算法课作业的python实现(四)8 Puzzle相关推荐

  1. 普林斯顿算法课作业的python实现(三)Collinear Points

    Collinear Points 问题 思路 代码 结果 问题 这一次的编程作业是判断共线点. 问题大致描述如下: 给定平面上一些点,判断其中是否有四个及以上的点共线,把所有这些点找出来并连线.原题链 ...

  2. 普林斯顿算法课作业 part II 的python实现(四)Boggle

    Boggle 问题 思路 代码 结果 总结 问题 原问题网页:Boggle 问题大致描述如下: 有一个 4×44\times44×4 的方格图,每一个格子上标有一个英文字母,现要从中寻找出英文单词. ...

  3. 「数据结构」普林斯顿算法课第二周作业

    「数据结构」普林斯顿算法课第二周作业 Algorithm I, Princeton 编程作业: Deques and Randomized Queues 思路 Deque.java Randomize ...

  4. 「数据结构」普林斯顿算法课第一周作业

    「数据结构」普林斯顿算法课第一周作业 Algorithm I, Princeton 编程作业: Percolation 思路 第一部分代码展示 第二部分代码展示 编程作业: Percolation P ...

  5. 普林斯顿算法课Part2第四周作业_Boggle

    作业地址:http://coursera.cs.princeton.edu/algs4/assignments/boggle.html 作业难点: 1.如何保证求解速度,满分要求是求解速度 >= ...

  6. 算法第四版课后习题答案 西安电子科技大学 计算机学院 算法课

    来源于西电计算机15级学长学姐,算法第四版课后习题答案 西安电子科技大学 计算机学院   算法课. 再推荐一个好的看答案的地方,每一题都有,只是还没有更新完成. 地址:https://alg4.ike ...

  7. WordNet 普林斯顿 算法第四版

    普林斯顿 算法第四版 本文的代码以及之前的作业代码可通过一下github链接获得 https://github.com/Changjing-Liu/algorithm_lab 文章目录 普林斯顿 算法 ...

  8. BoggleSolver 普林斯顿 算法第四版

    BoggleSolver 普林斯顿 算法第四版 文章目录 BoggleSolver 普林斯顿 算法第四版 一. 引言 1. Boggle 2. 计分 3. Qu特殊情况 4. 任务要求 二.分析 1. ...

  9. AcWing提高算法课Level-3 第四章 高级数据结构

    AcWing提高算法课Level-3 第四章 高级数据结构 并查集 AcWing 1250. 格子游戏1167人打卡 AcWing 1252. 搭配购买1064人打卡 AcWing 237. 程序自动 ...

最新文章

  1. html,css,js,反弹的js效果
  2. TP自动生成模块目录
  3. 史上最全的Chrome使用技巧集锦
  4. SAP Spartacus org unit table不同区域focus然后回车的行为差异
  5. mysql 字符转换函数是_MySQL日期和字符串转换函数
  6. 修改php上传限制 (phpmyadmin 限制)
  7. 深入解析MVVM架构
  8. IE7下JSON不能有多余的逗号,IE8下创建IMG节点的BUG
  9. java for mat,在Java绑定中通过OpenCV Mat进行循环
  10. Mysql中的日期及时间相关函数
  11. 山东理工计算机组成原理试题,山东理工计算机组成原理试题
  12. 废旧笔记本打造黑群晖NAS,docker,软路由,实现我心目中的all in one,包含fx n1,玩客云老母鸡玩法
  13. Launcher3 翻页动画详解与修改
  14. 什么是时间复杂度和空间复杂度
  15. 不懂英语怎么做亚马逊_亚马逊的回声秀可以做的一切其他回声都做不到
  16. 瀚高数据库故障诊断指导方案
  17. 计算机操作系统 - 目录1
  18. 三个变量存在一个协整方程_计量经济学最基本的31个问题
  19. 阿里巴巴数学竞赛详细解答(据说晋级的直接P8岗)
  20. 蚂蚁金服 Service Mesh 实践探索 | Qcon 实录

热门文章

  1. deepin深度系统安装方法
  2. 基于php+mysql购物商城 校园二手商品 图书鲜花商城 毕业设计(9)商品评论
  3. 北大软微和北邮计算机,各校MBA录取成绩分析,你的竞争者考得都挺高!
  4. 2023考研|上海财经大学MBA/EMBA招生录取流程正式发布-文都管联院
  5. 基础算法题——城市间最短路程(Floyd算法)
  6. 网站推广之搜索引擎篇(转)
  7. php 图片 字母识别,php实现ocr文字识别
  8. Ubuntu下安装Microsoft Teams
  9. 2022阿里云码上公益“第益课”大学生技术公益实践计划活动说明
  10. python爬虫入门(一)爬取钓鱼吧