深度优先搜索------走迷宫(求方案数)

题目概述:

题目描述
张三是一个玩迷宫的高手,天下还没有能难住他的迷宫。但是总有人喜欢刁难蒜头君,不停的给张三出难题。这个出题的人很聪明,他知道天下还没有能难住张三的迷宫。

所以他便转换思维问张三,在不走重复路径的情况下,总共有多少不同可以到达终点的路径呢?张三稍加思索便给出了答案,你要不要也来挑战一下?

输入格式
第一行输入两个整数 n(1 ≤ n ≤ 11), m(1 ≤ m ≤ 11),表示迷宫的行和列。

然后有一个 n × m 的地图,地图由 '.'、'#'、's'、'e' 这四个部分组成。'.'表示可以通行的路,'#'表示迷宫的墙,'s'表示起始点,'e'表示终点。

输出格式
输出一个整数,表示从 's' 到达 'e' 的所有方案数。

输入样例1
输入
3 3
##s
#..
e.#
输出
1
输入样例2
输入
3 3
##s
...
e.#
输出
2
输入样例3
输入
5 5
s####
.####
.####
.####
....e
输出
1
输入样例4
输入
5 5
s####
.####
.####
.####
..##e
输出
0
输入样例5
输入
6 6
s...##
.#..##
.#..##
.#....
.#....
.....e
输出
357

思路:

        在真实举办的迷宫游戏中,有些商家为了降低游戏的难度可能会赠与玩家空白的方格纸,当玩家无法前进时可以在方格纸对应的位置打上标志表示此路不通。同样我们可以定义两个二维数组,第一个数组记录真实的地图,第二个数组作为“方格纸”使用,同样可以将s,e在数组中的位置记录在全局变量,同样的为了方便可以在主函数外定义一个count = 0,来记录迷宫的方案数,lx,ly作为迷宫的规模,因为迷宫可以选择上下左右,所以需要额外额外定义一个二维数组来储存下一步的方向,走过的地方就在方格纸上标志为1,表示不需要再走一遍,如果接下来上下左右都走不通退回上一步,并且把本步所处位置的方格还原成0,遇到终点count就加1,表示找到一种方案。

具体代码:

#include<stdio.h>

char maza[100][100];//储存真实地图。

int visited[100][100] = { 0 };//标记走过的路。

int startx = 0, starty = 0;//起点位置。

int endx = 0, endy = 0;//终点位置。

int lx = 0, ly = 0;//地图的规模。

int dir[4][2] = {{1,0},{-1,0},{0,-1},{0,1}};//方向数组。

int count = 0;//计数器。

void dfs(int x, int y)

{

    if (x == endx && y == endy)

    {

        count++;

        return;

    }//如果走到终点,计数器加1,并且返回上一步。

    int tx, ty;//定义下一步的位置。

    for (int i = 0; i < 4; i++)

    {

        tx = x + dir[i][0];

        ty = y + dir[i][1];//四个方向依次遍历。

        if (tx < 0 || tx >= lx || ty < 0 || ty >= ly)

            continue;//如果下一步不在迷宫范围内,则继续循环,不进行下一步。

        if (visited[tx][ty] == 0 && maza[tx][ty] != '#')//如果下一步没有走过并且不为墙,就将下一步的位置标记为1,表示已经走过。

        {

            visited[tx][ty] = 1;

            dfs(tx, ty);//接着进行下一步。

            visited[tx][ty] = 0;//将该位置还原成0

        }

    }

    return;

}

int main(void)

{

    scanf("%d%d", &lx, &ly);

    char c;

    scanf("%c", &c);//处理换行符。

    for (int i = 0; i < lx; i++)

    {

        for (int j = 0; j < ly; j++)

        {

            scanf("%c", &maza[i][j]);

            if (maza[i][j] == 's')

            {

                startx = i;

                starty = j;//如果输入s,则记录s的位置。

            }

            if (maza[i][j] == 'e')

            {

                endx = i;

                endy = j;//如果输入e,则记录e的位置。

            }

        }

        scanf("%c", &c);//处理换行符。

    }

    visited[startx][starty] = 1;//起点标志为1.

    dfs(startx, starty);

    printf("%d", count);

}

注意点:

        这段代码需要注意的是一定要将起点的位置提前设置为1,我们可以想象一下,假设我们从起点出发,发现上面可以走,等我们走到上面后,将此地标记为1,然后循环方向数组发现下面(起点)也可以走,就又回到了起点,同时将上面的位置还原成0,然后发现上面又可以走了......,

        也就是说如果不提前将起点置1,则会陷入死循环,将这点搞懂,这段代码就很容易理解了。

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值