python数据结构学习笔记-2016-11-02-02-迷宫问题

        7.4 迷宫问题

        7.4.1 回溯

        蛮力法(brute-force method):穷举所有可能,一一验证。这种方法效率较低。

        回溯法(backtracking):通过部分返回来排除解决问题可能途径进而找出正确途径的过程,例如说解决迷宫问题就可以用回溯法。相应的算法称为回溯算法。

        7.4.2 设计解决方案

        问题细节

  • 首先是确定从起点到终点,是否有路径直达;
  • 该路径不能出现循环或回路。

        当我们在迷宫移动一步时,首先不能碰到墙,其次不能走之前走过的路(分叉路口试验路径时另外考虑)。此外,移动方向只能是上下左右。

        用”x”表示已经走过的路,用”o”表示死路,用”X”表示当前位置。

        算法描述

        寻找出口,从起点出发,检测四周,有哪些方向可走(按上下左右的顺序来检测),找出方向之后,在移动之前,在目前的位置做下标记,如”x”。当遇到死路时,也做下标记”o”,然后回到分叉点。如

《python数据结构学习笔记-2016-11-02-02-迷宫问题》

         从起点到终点,也有可能不存在一条路径。

《python数据结构学习笔记-2016-11-02-02-迷宫问题》

          迷宫ADT

  • Maze(numRows, numCols):创建迷宫,大小为numRows × numCos,其内所有格子设置为空,起点和终点均为None;
  • numRows():返回numRows;
  • numCols():返回numCols;
  • setWall(row, col):将(row, col)的格子设定为墙;
  • setStart(row, col):设定起点;
  • setExit(row, col):设定终点;
  • findPath():寻找路径,如果路径存在,标记x,返回True;如果不存在,返回False;
  • reset():去除标记,返回出发时的状态;
  • draw():以可读形式打印迷宫,如果从起点到终点存在路径,显示路径。

          例子使用

#-*-coding: utf-8-*-

# 从文件中建立迷宫,并解决迷宫

from maze 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():
        print "Path found ..."
        maze.draw()
    else:
        print "Path not found ..."

if __name__ == "__main__":
    main()    

       迷宫文件形式

       第一行是迷宫大小,第二三行分别是起点和终点,之后是墙的分布。

 《python数据结构学习笔记-2016-11-02-02-迷宫问题》 

       7.4.4 实现

       最适合表示迷宫的数据结构就是二维数组了。

#-*-coding: utf-8-*-

# 迷宫ADT

from myarray2d import Array2D
from lliststack import Stack

class Maze(object):
    MAZE_WALL = "*" # 墙
    PATH_TOKEN = "x" # 表示走过的路径
    TRIED_TOKEN = "o" # 死路

    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 findPath(self):
        dirctions = [(-1, 0), (0, 1), (1, 0), (0, -1)] # 方向集
        path = Stack()
        path.push(self._startCell)
        while not path.isEmpty():
            curPos = path.peek() # 栈顶表示当前位置
            if self._exitFound(curPos.row, curPos.col): # 检测当前位置是否就是终点
                self._markPath(curPos.row, curPos.col)
                break
            chioce = 0
            for dirction in dirctions: # 先找出有多少种选择
                if self._validMove(curPos.row + dirction[0], curPos.col + dirction[1]):
                    chioce += 1
            if chioce == 0: # 如果不能移动,就将当前位置标记为'o',并弹出栈
                self._markTried(curPos.row, curPos.col)
                path.pop()
            else: # 如果能移动,标记当前位置为'x',然后选择一个方向进行尝试,直到走到死路或者找到终点。
                for dirction in dirctions:
                    if self._validMove(curPos.row + dirction[0], curPos.col + dirction[1]):                        
                        self._markPath(curPos.row, curPos.col)
                        nextPos = _CellPosition(curPos.row + dirction[0], curPos.col + dirction[1])
                        path.push(nextPos)
                        break
        if len(path):
            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

       其中在寻找路径函数findPath()中,就可以用到栈。将走过的路,压入栈中,如果遇到死路,就将其弹出栈,直到找到出路或者确定没有路径为止。

    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/baidu_21088863/article/details/53012448
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞