【万题详解】洛谷P1238 走迷宫

题目

有一个 m×n 格的迷宫(表示有 m 行、n 列),其中有可走的也有不可走的,如果用 1表示可以走,0表示不可以走,文件读入这 m×n 个数据和起始点、结束点(起始点和结束点都是用两个数据来描述的,分别表示这个点的行号和列号)。现在要你编程找出所有可行的道路,要求所走的路中没有重复的点,走时只能是上下左右四个方向。如果一条路都不可行,则输出相应信息(用 −1 表示无路)。

优先顺序:左上右下。数据保证随机生成。

输入格式

第一行是两个数 m,n(1

输出格式

所有可行的路径,描述一个点时用 (x,y) 的形式,除开始点外,其他的都要用 -> 表示方向。

如果没有一条可行的路则输出 −1。

输入输出样例

输入 #1

5 6
1 0 0 1 0 1
1 1 1 1 1 1
0 0 1 1 1 0
1 1 1 1 1 0
1 1 1 0 1 1
1 1
5 6

输出 #1

(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(3,4)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(3,4)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)

说明/提示

数据保证随机生成。事实上,如果 n=m=14 且每个位置都是 1 的话,有 69450664761521361664274701548907358996488 种路径。

题目有点多!

解题思路

题目坑点:

1.如果没有解要输出-1。

2.搜索前进的方向要遵循左上右下的优先顺序。

3.首先需要仔细模拟确定行走方向,左下右上(同2)

其实深搜可以写成两种形式,递归和递推形式,但实际上本人跟喜欢递推形式的。

一般情况

首先看题,在不考虑输出路径的情况下这就是一个普通的搜索

对于一般情况来说我们只需要对当前位置向四周搜索就行了。

这时我们需要考虑3点: 1.对于达到终点的情况; 2.对于该点是否能走的情况

对于1.这是我们递龟递归的终点,在到达这里时便可以结束搜索

而对于2.我们要判断该点是否可走。对于迷宫中的0和已走过的点(避免单一路径中重复输出)不能走,因此使用一个二维数组来存放。

对于路径储存

我们通过看题目还可以知道:

本题目除了常规的深搜外还要记录搜索路径。因此我们使用Vector来存储(相当于一个可以伸缩的数组)。

我们将每一个搜索的点都放入数组中,退出时删除。 在搜到重点时输出 。

这题感觉就基本上裸dfs修改一下限制条件之后再写个输出函数和路径数组就好了。

主要就这些:

1.肯定是搜索(dfs/bfs)

2.有四个方向

3.定义dx[]和dy

4.先定义各种奇奇怪怪的东西

5.然后再打一下打印过程

6.开始搜索

7.注意方向及顺序

8.坐标分为横坐标和纵坐标

9.所以用struct好一些(或者用pair)

10.搜索时按照四个方向

11.对于每个方向,要递归一下

12.不要忘了回溯

13.注意搜索时坐标有条件,map数组也有条件(详见代码)

14.主函数别忘了初始化

15.提交,WA,前两个点错了

16.为什么为什么(要判断,定义一个flag)

17.最后输出-1

18.提交,AC

最后附上链接——题目在这里!!!没有账号的要先注册(应该不用说了)

如何注册洛谷账号,请看下面:

1.打开洛谷首页

【万题详解】洛谷P1238 走迷宫_第1张图片

这样就对了!!!

2.点击注册

【万题详解】洛谷P1238 走迷宫_第2张图片

当显示以上页面时表示进入了注册页面。

3.登录

当注册好后就可以登陆了。

【万题详解】洛谷P1238 走迷宫_第3张图片

当显示以上页面时表示进入了登录页面。

AC

#include 
#include 
using namespace std;
const int N = 5000;
const int dx[4] = {0, -1, 0, 1}, dy[4] = {-1, 0, 1, 0};
int g[N][N], d[N][5];
bool map[N][N];
int n, m, sx, sy, ex, ey, f, ans;
void dfs(int x1, int y1)
{
    if(x1 == ex && y1 == ey)
    {
        ans ++;
        cout << '(' << sx << ',' << sy << ')' << "->";
        for(int i = 0; i < f; i ++ )
        {
            if(i != f - 1)  cout << '(' << d[i][0] << ',' << d[i][1] << ')' << "->";
            else  cout << '(' << d[i][0] << ',' << d[i][1] << ')' << endl;
        }
        return ;
    }
    for(int i = 0; i < 4; i ++ )
    {
        int x = x1 + dx[i], y = y1 + dy[i];
        if(x >= 1 && x <= n && y >= 1 && y <= m && !map[x][y] && g[x][y] == 1)
        {
            map[x][y] = true;
            d[f][0] = x, d[f][1] = y; 
            f ++;
            dfs(x, y);
            map[x][y] = false;
            f --;
        }
    }
}
signed main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++ )
    {
        for(int j = 1; j <= m; j ++ )  scanf("%d", &g[i][j]);
    }
    scanf("%d%d%d%d", &sx, &sy, &ex, &ey);
    map[sx][sy] = true; //标记起点
    dfs(sx, sy);
    if(ans == 0)  cout << -1 << endl;
}

你可能感兴趣的:(c++,算法,搜索)