zoukankan      html  css  js  c++  java
  • 迷宫实现递归版本C++

    迷宫实现递归版本C++

    问题描述:

    ////////////////////////////////////////////////////////////
    //题目:迷宫求解问题。

    大致思路:

    //1、入口,出口判断/程序终止判定:4个方位的坐标边界比较,表明到了出入口。
    //2-1、求解原理1:暴力处理,从入口点开始,对其四个方向进行可行性判别,获取下一位置,重复,知道走到出口。
    //2-2、求解原理2:对于有出口的迷宫,如果你一直靠右,或者靠左行走,必然能够走到出口。这个方案省去了1中暴力队每个方向的判别。
    //3、走过的路线,具体坐标的值修改为2,然后将走过的点坐标入栈保存。
    //4、优化点①:可能存在死胡同或者环形路线,那么必然会绕远路。所以对3、中的修改值为2改进为+=2,可以具体得出经过某位置几次
    //5、优化点②:根据3、 4、可以判断出走过的没必要的路线,记录值为4的点,然后对栈进行出栈操作,可以做到优化部分路线。
    //6、待完善点:没有给出迷宫最短路线的解答。
    ////////////////////////////////////////////////////////////

    //工程目录下 MazeMap.txt中的地图表示

    //1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    //1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    //0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
    //1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1
    //1 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 0 1 1
    //1 1 0 0 0 1 0 1 1 1 1 1 0 1 1 1 1 0 1 1
    //1 1 0 1 0 0 0 1 1 1 1 1 0 1 1 1 1 0 1 1
    //1 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 1 1
    //1 1 0 1 0 0 0 1 1 1 1 1 0 1 1 1 1 0 1 1
    //1 1 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 0 1 1
    //1 1 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 0 1 1
    //1 1 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 0 1 1
    //1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1
    //1 1 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1
    //1 1 0 0 0 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1
    //1 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1
    //1 1 0 1 0 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1
    //1 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1
    //1 1 0 1 0 0 0 1 0 0 0 1 1 1 1 1 1 1 1 1
    //1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

    代码示例:

    //由文件读取迷宫地图。
    void
    GetMazeMap(int *a,int row,int col) { FILE *FOut; fopen_s(&FOut,"MazeMap.txt", "r"); assert(FOut); for (int i = 0; i < row; ++i) { for (int j = 0; j < col;) { char ch = fgetc(FOut); if (ch == '0' || ch == '1') { a[i*col + j] = ch - '0'; ++j; } } } }
    //迷宫打印
    void PrintMazeMap(int *a, int row, int col) { cout << "MazeMap:(row,col):(" << row <<","<< col <<")."<< endl; for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { cout << a[i*col + j] << " "; } cout << endl; } cout << endl; }

    //位置坐标类。
    struct Step { int row;// int col;// bool operator==(Step &s) { return row == s.row&&col == s.col; } };

    //在程序中对迷宫进行遍历时除了坐标,更给出具体方向的类man
    struct man { man(Step s, int d) :_cur(s) , _dir(d) {} Step _cur; int _dir;// 0-3 表明4个方向 man nextPos(int dir) { Step cur = _cur; dir = (dir+4) % 4; switch (dir) { case 0: cur.row--; break; case 1: cur.col++; break; case 2: cur.row++; break; case 3: cur.col--; break; } return man(cur, dir); } }; stack<man> paths;
    //打印具体走过的迷宫路线的坐标(含方向)
    void PrintPathStep() { while (!paths.empty()) { man tmp = paths.top(); cout << "[" << tmp._cur.row << "," << tmp._cur.col << "]:" << tmp._dir << "" << "-->"; paths.pop(); } cout << "Over!" << endl; } //给定map和入口点坐标,求迷宫解 void GetMazePaths(int *map, int row, int col, Step& entry) { //当前位置. man m(entry, 0); map[m._cur.row*col + m._cur.col] = 2; paths.push(m); while (1) { man top = paths.top(); man cur = top.nextPos(top._dir - 1); //man cur = top.nextPos(top._dir + 1); 可替换上行,转换为靠右行。

    if (cur._cur.col<0 || cur._cur.row<0 || cur._cur.col>=col || cur._cur.row>=row) { cout << "越界" << endl; top._dir++; //top._dir--; 可替换上行,转换为靠右行 paths.pop(); paths.push(top); continue; } //边界,也就是出入口 if ((cur._cur.col == 0 || cur._cur.row == 0 || cur._cur.col == col-1 || cur._cur.row == row-1) &&map[cur._cur.row*col + cur._cur.col] == 0) { cout << "这里是出入口" << endl; if (!(cur._cur == entry)) { map[cur._cur.row*col + cur._cur.col] = 2; paths.push(cur); cout << "得到出口" <<cur._cur.row<<" "<<cur._cur.col<< endl; break; } } //遍历: //下一个位置为当前方向的下一个位置 if (map[cur._cur.row*col + cur._cur.col] != 1) { map[cur._cur.row*col + cur._cur.col] += 2; if (map[cur._cur.row*col + cur._cur.col] == 4) { Step tmp; tmp.row = cur._cur.row; tmp.col = cur._cur.col; ////////////////////////////////////////////////////////////////////////////// //回退过程。 while (paths.top()._cur.row != tmp.row || paths.top()._cur.col != tmp.col) { map[paths.top()._cur.row*col + paths.top()._cur.col] = 1; paths.pop(); } } map[cur._cur.row*col + cur._cur.col] = 2; paths.push(cur); } else { top._dir++; //top._dir--; 可替换上行,转变为靠右行方案 paths.pop(); paths.push(top); } } }

    //递归方式求解迷宫路线问题。思路为靠左行方案
    //注:递归方式没有如非递归方式的死胡同排除等优化,只是单纯的靠左行得到路线。
    void GetNextAccessPath(int *map, int row, int col, man& entry) { man tmp(entry); if ( ( entry._cur.row == row - 1 || entry._cur.col == col - 1 ||entry._cur.row == 0 // || entry._cur.col == 0 //注,这一行的注释主要是明确出口的具体位置不是左边。 可以改进为结束判断是:该点是边界,但不是程序传入的迷宫入口。(即是出口)
    ) && map[entry._cur.row*col + entry ._cur.col] != 1 ) { paths.push(entry); return; } else { paths.push(entry); tmp = entry.nextPos(entry._dir-1);
        //获得下一个可以通行的位置
    while (map[tmp._cur.row*col + tmp._cur.col] == 1) { tmp = entry.nextPos(tmp._dir+1); } entry = tmp; GetNextAccessPath(map, row, col, entry); } } void main() { int a[20][20] = {}; ::GetMazeMap((int*)a, 20, 20); Step ent = { 2, 0 }; man entm = { { 2, 0 }, 1 }; GetMazePaths((int*)a, 20, 20, ent); //非递归方式 //GetNextAccessPath((int*)a, 10, 10, man(ent, 0)); //递归方式 ::PrintMazeMap((int*)a, 20, 20); ::PrintPathStep(); system("pause"); }

    运行结果实例:

    得到出口19 2
    MazeMap:(row,col):(20,20).
    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1
    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1
    1 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 2 1 1
    1 1 0 0 0 1 0 1 1 1 1 1 0 1 1 1 1 2 1 1
    1 1 0 1 0 0 0 1 1 1 1 1 0 1 1 1 1 2 1 1
    1 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 2 1 1
    1 1 0 1 0 0 0 1 1 1 1 1 0 1 1 1 1 2 1 1
    1 1 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 2 1 1
    1 1 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 2 1 1
    1 1 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 2 1 1
    1 1 0 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1
    1 1 0 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1
    1 1 2 2 2 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1
    1 1 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1
    1 1 2 1 2 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1
    1 1 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1
    1 1 2 1 2 2 2 1 0 0 0 1 1 1 1 1 1 1 1 1
    1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

    [19,2]:2--> [18,2]:3--> [17,2]:3--> [16,2]:3--> [15,2]:3--> [14,2]:3--> [14,3]:4--> [14,4]:0--> [15,4]:1--> [16,4]:1--> [17,4]:1--> [18,4]:5--> [18,5]:4--> [18,6]:4--> [17,6]:3-->
    [16,6]:3--> [15,6]:3--> [14,6]:3--> [13,6]:3--> [12,6]:3--> [12,7]:4--> [12,8]:4--> [12,9]:4--> [12,10]:4--> [12,11]:4--> [12,12]:0--> [12,12]:3--> [12,13]:4--> [12,14]:4--> [12,15]:4-->
    [12,16]:4--> [12,17]:4--> [11,17]:3--> [10,17]:3--> [9,17]:3--> [8,17]:3--> [7,17]:3--> [6,17]:3--> [5,17]:3--> [4,17]:3--> [3,17]:3--> [2,17]:3--> [2,16]:2--> [2,15]:2--> [2,14]:2-->
    [2,13]:2--> [2,12]:2--> [2,11]:2--> [2,10]:2--> [2,9]:2--> [2,8]:2--> [2,7]:2--> [2,6]:2--> [2,5]:2--> [2,4]:2--> [2,3]:2--> [2,2]:2--> [2,1]:2--> [2,0]:2--> Over!

    注:程序中的地图大小可由文件中定义给出。

    然后数组表示可以改进为动态分配。

    具体关于二维数组做参数或如何动态申请二维数组的方案可参考:Effective-C++.

  • 相关阅读:
    Java 数据库操作oracle增删改查,通用封装基于hashmap
    Python 自动化paramiko操作linux使用shell命令,以及文件上传下载linux与windows之间的实现
    Java利用 ganymedssh2build.jar来上传文件到linux以及下载linux文件以及执行linux shell命令
    Java Calendar and SimpleDateFormat 时间模块
    Java 读取properties
    Java java httpclient4.5 进行http,https通过SSL安全验证跳过,封装接口请求 get,post(formdata,json)封装,文件上传下载
    Python 基于request库的get,post,delete,封装
    更法第一 (zz)
    北京将投资707亿元建三条地铁新线 (zz.IS2120@BG57IV3)
    fgetws 讀取Unicode文件 (zz.IS2120@BG57IV3)
  • 原文地址:https://www.cnblogs.com/lang5230/p/5260330.html
Copyright © 2011-2022 走看看