python数据结构学习笔记-2017-01-08-01-N皇后问题、迷宫问题和跳马问题的递归解决
来源:互联网 发布:数控机床与编程教程 编辑:程序博客网 时间:2024/06/05 16:44
N皇后问题
棋盘ADT
#-*-coding: utf-8-*-# 二维数组实现棋盘ADTfrom myarray2d import Array2Dclass Board(object): def __init__(self, n): self._board = Array2D(n, n) self._size = n def size(self): return self._size def numQueens(self): count = 0 for row in range(self.size()): for col in range(self.size()): if self._board[row, col] == 1: count += 1 return count def unguarded(self, row, col): if self._board[row, col]: return False else: directions = [(0, 1), (0, -1), (-1, 0), (1, 0), (1, 1), (-1, -1), (1, -1), (-1, 1)] for direction in directions: r = row c = col while 0 <= r < self.size() and 0 <= c < self.size(): if self._board[r, c] == 1: return False else: r += direction[0] c += direction[1] return True def placeQueen(self, row, col): assert self.unguarded(row, col), "Cannot place a queen here." self._board[row, col] = 1 def removeQueen(self, row, col): self._board[row, col] = 0 def reset(self): for row in range(self.size()): for col in range(self.size()): if self._board[row, col] == 1: self.removeQueen(row, col) def draw(self): for row in range(self.size()): string = '' for col in range(self.size()): if self._board[row, col]: string += '@ ' else: string += '. ' print string递归解决N皇后问题,返回解的个数,修改一下,也可以返回全部解。
#-*-coding: utf-8-*-# N皇后问题from board import Board# 该函数只是验证N皇后问题解的存在性def solveNQueens(board, col): if board.numQueens() == board.size(): # 确定所有皇后是否都放置好了 return True else: # 在这一列找出正确的位置放置皇后 for row in range(board.size()): if board.unguarded(row, col): board.placeQueen(row, col) if solveNQueens(board, col+1): return True else: board.removeQueen(row, col) return False # 没有找到正确位置,则会回溯到上一列的皇后放置上来。# 返回的count是solveNQueensCounts(board, col),其中的col是最开始的0,如果使用局部变量有些麻烦,用全局变量就相对好处理一些。count = 0def solveNQueensCounts(board, col): for row in range(board.size()): if board.unguarded(row, col): board.placeQueen(row, col) if board.numQueens() == board.size(): # 确定找到一个解了 # board.draw() global count count += 1 board.removeQueen(row, col) # 确定一个解后,需要将最后一个皇后拿掉 else: solveNQueensCounts(board, col+1) board.removeQueen(row, col) # 无论在col+1列放置皇后是否成功,都必须将原来在col列放置的皇后拿掉,再尝试在该列的下一个位置。因为col+1列没有放置成功,显然放置在col列的皇后要拿掉。如果在col+1列放置成功,并找到了在前面col列的皇后都不动的情况下的所有解之后,要寻找接下来的解,显然也要移动col列上的皇后。 return countif __name__ == "__main__": n = int(raw_input("Please enter the size of board: ")) board = Board(n) # solveNQueens(board, 0) # board.draw() print solveNQueensCounts(board, 0)
迷宫问题
迷宫ADT
#-*-coding: utf-8-*-# 迷宫ADTfrom myarray2d import Array2D# from lliststack import Stackclass Maze(object): MAZE_WALL = "*" # 墙 PATH_TOKEN = "x" # 表示走过的路径 TRIED_TOKEN = "o" # 死路 PathFound = False def __init__(self, numRows, numCols): self._mazeCells = Array2D(numRows, numCols) self._startCell = None self._exitCell = None def numRows(self): return self._mazeCells.numRows() def numCols(self): return self._mazeCells.numCols() def setWall(self, row, col): assert 0 <= row < self.numRows() and 0 <= col < self.numCols(), "Cell index out of range." self._mazeCells[row, col] = Maze.MAZE_WALL def setStart(self, row, col): assert 0 <= row < self.numRows() and 0 <= col < self.numCols(), "Cell index out of range." self._startCell = _CellPosition(row, col) def setExit(self, row, col): assert 0 <= row < self.numRows() and 0 <= col < self.numCols(), "Cell index out of range." self._exitCell = _CellPosition(row, col) def getStart(self): return self._startCell.row, self._startCell.col def getExit(self): return self._exitCell.row, self._exitCell.col def findPath(self, row, col): self._markPath(row, col) # 首先对当前位置进行标记'x' # print row, col if self._exitFound(row, col): # 确认当前位置是否是终点,是就修改类属性Maze.PathFound Maze.PathFound = True else: chioce = 0 # 先确定在这一位置上是否有路可走 dirctions = [(0, 1), (1, 0), (0, -1), (-1, 0)] for dirction in dirctions: r = row + dirction[0] c = col + dirction[1] if self._validMove(r, c): chioce += 1 if chioce == 0: # 若无路可走则标记'o' self._markTried(row, col) else: for dirction in dirctions: r = row + dirction[0] c = col + dirction[1] if Maze.PathFound: # 一旦确认已到达终点,停止递归调用,进入递归返回 break if self._validMove(r, c): self.findPath(r, c) if Maze.PathFound: # 确认是否找到到达终点的路径 return True else: return False # 删除所有标记,即"x"和"o"。 def reset(self): for row in range(self.numRows()): for col in range(self.numCols()): if self._mazeCells[row, col] in 'ox': self._mazeCells[row, col] = None def draw(self): for row in range(self.numRows()): str = '' for col in range(self.numCols()): if self._mazeCells[row, col] != None: str += self._mazeCells[row, col] else: str += '.' print str # 是否能移动到该位置 def _validMove(self, row, col): return 0 <= row < self.numRows() and 0 <= col < self.numCols() and self._mazeCells[row, col] is None # 判断当前点是否为终点 def _exitFound(self, row, col): return row == self._exitCell.row and col == self._exitCell.col # 将该位置设置为死路 def _markTried(self, row, col): self._mazeCells[row, col] = Maze.TRIED_TOKEN # 标记走过的路 def _markPath(self, row, col): self._mazeCells[row, col] = Maze.PATH_TOKEN# 储存类class _CellPosition(object): def __init__(self, row, col): self.row = row self.col = col递归解决迷宫问题
#-*-coding: utf-8-*-# 从文件中建立迷宫,并解决迷宫from recmaze import Maze# 建立迷宫def buildMaze(filename): with open(filename, 'r') as infile: nrows, ncols = readValuePair(infile) # 迷宫大小 maze = Maze(nrows, ncols) # 建立迷宫,并初始化 row, col = readValuePair(infile) maze.setStart(row, col) # 根据给定坐标设定起始点 row, col = readValuePair(infile) maze.setExit(row, col) for row in range(nrows): line = infile.readline() for col in range(len(line)): if line[col] == "*": maze.setWall(row, col) infile.close() return maze# 辅助方法,从给定文件中读取整数对值def readValuePair(infile): line = infile.readline() (valA, valB) = tuple(line.split()) return int(valA), int(valB)def main(): maze = buildMaze("mazefile.txt") if maze.findPath(maze.getStart()[0], maze.getStart()[1]): print "Path found ..." maze.draw() else: print "Path not found ..."if __name__ == "__main__": main()
跳马问题
棋盘ADT
#-*-coding: utf-8-*-# 跳马问题国际象棋棋盘ADTfrom myarray2d import Array2Dclass ChessBoard(object): PATH_FOUND = False COUNT = 0 def __init__(self, n): self._board = Array2D(n, n) self._size = n self._start = None def size(self): return self._size def setStart(self, row, col): assert 0 <= row < self._size and 0 <= col < self._size, "Out of range." self._start = _CellPosition(row, col) def _validMove(self, row, col): return 0 <= row < self._size and 0 <= col < self._size and self._board[row, col] == None # 寻找路径 def findPath(self, row, col): # print row, col self._board[row, col] = ChessBoard.COUNT ChessBoard.COUNT += 1 if ChessBoard.COUNT == self._size ** 2: # 通过步数来判断棋盘是否已经遍历完 ChessBoard.PATH_FOUND = True else: choice = 0 directions = [(1, 2), (2, 1), (-1, -2), (-2, -1), (1, -2), (-1, 2), (-2, 1), (2, -1)] # 方向 for direction in directions: r = row + direction[0] c = col + direction[1] if self._validMove(r, c): choice += 1 if choice: for dirction in directions: r = row + dirction[0] c = col + dirction[1] if self._validMove(r, c): self.findPath(r, c) else: self._board[row, col] = None ChessBoard.COUNT -= 1 return False if ChessBoard.PATH_FOUND: print row, col return True else: self._board[row, col] = None # 注意如果一个位置有路可走,但经试验都是死路的话,必须将这个位置复原! class _CellPosition(object): def __init__(self, row, col): self.row = row self.col = col递归解决跳马问题
#-*-coding: utf-8-*-from recchessboard import ChessBoarddef knightTour(board, row, col): if isinstance(board, ChessBoard): board.setStart(row, col) board.findPath(row, col)if __name__ == "__main__": board = ChessBoard(5) row = int(raw_input("Please enter a positive integer less than 5: ")) col = int(raw_input("Please enter a positive integer less than 5: ")) knightTour(board, row, col) print board.COUNT
以上的代码还是有不少可优化的空间。
0 0
- python数据结构学习笔记-2017-01-08-01-N皇后问题、迷宫问题和跳马问题的递归解决
- 回朔法和递归解决八皇后和跳马问题
- N 皇后问题及跳马问题
- 数据结构学习----“八皇后”问题的解决
- n皇后问题【递归】
- 递归 N皇后问题
- N皇后问题 (递归)
- 递归---n皇后问题
- N皇后问题的非递归回溯和递归回溯
- N皇后问题的解决
- [数据结构] N皇后问题
- 数据结构用栈解决n皇后问题
- 算法学习之递归--N皇后问题
- 回溯算法--迷宫问题和N皇后问题
- N皇后问题(递归回溯的学习)
- n 皇后问题的递归和回溯实现 C++
- C递归的N皇后问题.
- N皇后问题的递归回溯实现
- Java学习篇之IO流(字节流)
- 远程实习第一周学习总结
- 同时安装python2.x和python3.x用pip
- Oracle优化07-分析及动态采样-DBMS_STATS 包
- 关闭csrf办法
- python数据结构学习笔记-2017-01-08-01-N皇后问题、迷宫问题和跳马问题的递归解决
- OpenGL 入门13
- 翻译:结合卫星图像和机器学习预测贫穷
- JAVA 多线程
- tomcat出现403问题
- Swift-内存管理(初级)
- 深入理解Java虚拟机:垃圾收集
- 一些投资理财渠道(仅供参考)
- 一念永恒 > 第520章 黑色光柱!