ACM. HJ43 迷宫问题 ●●

HJ43 迷宫问题 ●●

描述

定义一个二维数组 N*M ,如 5 × 5 数组下所示:

int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线。入口点为[0,0],既第一格是可以走的路。

数据范围: 2 ≤ n , m ≤ 10 2≤n,m≤10 2n,m10 , 输入的内容只包含 0 ≤ v a l ≤ 1 0≤val≤1 0val1

输入描述:

输入两个整数,分别表示二维数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。

输出描述:

左上角到右下角的最短路径,格式如样例所示。

示例

输入:
5 5
0 1 0 0 0
0 1 1 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

输出:
(0,0)
(1,0)
(2,0)
(2,1)
(2,2)
(2,3)
(2,4)
(3,4)
(4,4)

题解

1. 回溯法

本题看似求最短路径,其实题目只有一条路径可走,因此采用回溯法进行深度优先搜索。

把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解。

深度优先搜索的思想是沿着一个方向搜到底,如果行不通,则返回来试其他的路径。就一直这样直到找到一条通路输出就可以了。

#include <iostream>
#include <vector>
#include <string>
using namespace std;
 
bool getPath(int currn, int currm, vector<vector<int>>& maze, vector<string>& ans){
    int n = maze.size();
    int m = maze[0].size();
    
    maze[currn][currm] = 1;		// 该点加入路径,并标记
    string pos = "(" + to_string(currn) + "," + to_string(currm) + ")";
    ans.emplace_back(pos);
    
    if(currn == n-1 && currm == m-1) return true;	// 到达终点 
 
    if(currn-1 >= 0 && maze[currn-1][currm] == 0){     // up
        if(getPath(currn-1, currm, maze, ans)) return true;
    }
 
    if(currn+1 <= n-1 && maze[currn+1][currm] == 0){  // down
        if(getPath(currn+1, currm, maze, ans)) return true;
    }
 
    if(currm-1 >= 0 && maze[currn][currm-1] == 0){     // left
        if(getPath(currn, currm-1, maze, ans)) return true;
    }
 
    if(currm+1 <= m-1 && maze[currn][currm+1] == 0){  // right
        if(getPath(currn, currm+1, maze, ans)) return true;
    }
 
    ans.pop_back();				// 走不通,回溯,恢复现场
    maze[currn][currm] = 0;
    return false;
}
 
 
int main(){
    int n, m;
    cin >> n >> m;
    vector<vector<int>> maze(n, vector<int>(m, 0));
    for(int i = 0; i < n; ++i){
        for(int j = 0; j < m; ++j){
            cin >> maze[i][j];
        }
    }
    vector<string> ans;
    getPath(0, 0, maze, ans);
    for(auto str: ans){
        cout << str << endl;
    }
    return 0;
}

如果题目中不止一条路径,则需要建立一个数组存储最短路径,同时递归回溯函数不使用返回值,而是遍历所有可能的路径,当找到新路径到达终点时则与最优路径进行比较。

#include <iostream>
#include <vector>
#include <string>
using namespace std;
 
void getMinPath(int currn, int currm, vector<vector<int>>& maze, vector<string>& currPath, vector<string>& minPath){
    int n = maze.size();
    int m = maze[0].size();
    
    maze[currn][currm] = 1;		// 该点加入路径,并标记
    string pos = "(" + to_string(currn) + "," + to_string(currm) + ")";
    currPath.emplace_back(pos);
    
    if(currn == n-1 && currm == m-1){   // 到达终点,比较最优
        if(minPath.empty()){
            minPath = currPath;
        }else if(currPath.size() < minPath.size()){
            minPath = currPath;
        }
    } 	
 
    if(currn-1 >= 0 && maze[currn-1][currm] == 0){     // up
        getMinPath(currn-1, currm, maze, currPath, minPath);
    }
 
    if(currn+1 <= n-1 && maze[currn+1][currm] == 0){  // down
        getMinPath(currn+1, currm, maze, currPath, minPath);
    }
 
    if(currm-1 >= 0 && maze[currn][currm-1] == 0){     // left
        getMinPath(currn, currm-1, maze, currPath, minPath);
    }
 
    if(currm+1 <= m-1 && maze[currn][currm+1] == 0){  // right
        getMinPath(currn, currm+1, maze, currPath, minPath);
    }
 
    currPath.pop_back();				// 走不通,回溯,恢复现场
    maze[currn][currm] = 0;
}

int main(){
    int n, m;
    cin >> n >> m;
    vector<vector<int>> maze(n, vector<int>(m, 0));
    for(int i = 0; i < n; ++i){
        for(int j = 0; j < m; ++j){
            cin >> maze[i][j];
        }
    }
    vector<string> currPath, minPath;
    getMinPath(0, 0, maze, currPath, minPath);
    for(auto str: minPath){
        cout << str << endl;
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值