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
原创粉丝点击