迷宫问题

dfs应用深度优先搜索

迷宫由n行m列的单元格组成,每个单元格要么是空地,要么是障碍物
找一条最短路径。
分析:用一个二维数组存储这个迷宫。刚开始的时候,在(1,1),
目标在(p,q),找(1,1)到(p,q)的最短路径。刚开始在(1,1)只能向
下或者向右走。先往右走,知道走不同的时候回到这里,再去尝试另外一个方向。按照顺时针方式尝试。

dfs函数的编写只需要维护三个参数,分别是当前目标点的坐标和已经走过的步数。

void dfs(int x, int y, int step)
{
    return 0;
}

判断是否到达目标位置的方式和目标节点是否已经实现了。如果相等则证明已经到达了目标节点。

void dfs(int x, int y, int step)
{
    //判断是否到达目标地址
    if(x==p && y==q){
        if(step < min)
            min = step;
        return;
    }
    return 0;
}

没有到达指定的位置,则可以找出下一步可以走的位置。因为有四个方向可以走,根据约定,按照顺时针方向来尝试,定义一个next数组,如下

int next[4][2] = 
{
    {0, 1}//向右走
    {1,0}//向下走
    {0, -1},//向左走
    {-1, 0}//向上走
}

通过这个方向数组,使用循环很容易获得下一步的坐标。横坐标用tx存储,纵坐标用ty存储。

for(k=0; k<=3;k++)
{
    //计算的下一个点的坐标
    tx=x+next[k][0];
    ty=y+next[k][1];
}

接下来对点(tx, ty)进行一些判断。包括是否越界,是否为障碍物,以及这个点是否在路径中(避免重复访问一个点)。需要用book[x][y]来记录格子(tx, ty)是否已经在路径中。
如果这个点已经符合所有的要求,就对这个点进行下一步的扩展,即dfs(tx, ty, step+1).

for(k=0; k<=3; k++)
{
    //计算下一点的坐标
    tx=x+next[k][0];
    ty=y+next[k][1];

    //判断是否越界
    if(tx<1 || tx>n || ty<1 || ty>m)
        continue;
    //判断该点是否为障碍物或者已经在路上了
    if(a[tx][ty] == 0 && book[tx][ty] == 0)
    {
         book[tx][ty] == 1;//标记这个点已经走过
         dfs(tx, ty, step+1);
         book[tx][ty] = 0;//尝试结束
    }
}

完整代码

#include<stdio.h>
int m,n,p,q, min=99999999;
int a[51][51], book[51][51];
void dfs(int x, int y, int step)
{
    int next[4][2] = {
        {0,1},//向右走
        {1,0},//向下走
        {0,-1},//向走左
        {-1,0}//向上走
        };  
    int tx, ty, k;
    //判断是否到达最小的位置
    if(x==p && y==q){
        //更新最小值
        if(step< min)
            min = step;
        return;
    }

    //枚举四种走法
    for(k=0; k<=3; k++){
        //计算下一个点坐标
        tx = x + next[k][0];
        ty = y + next[k][1];

        //判断是否越界
        if(tx<1 || tx>n || ty<1 || ty>m)
            continue;
        //判断该点是否为障碍物或者已经走过
        if(a[tx][ty]==0 && book[tx][ty]==0)
        {
            book[tx][ty] = 1;//标记这个点已经走过
            dfs(tx, ty, step+1);
            book[tx][ty] = 0;
        }
    }
}
int main()
{
    int i, j, startx, starty;

    //读入n和m, n为行, m为列
    scanf("%d %d", &n, &m);

    for(i=1;i<=n; i++)
        for(j=1; j<=m; j++)
            scanf("%d", &a[i][j]);

    scanf("%d %d %d %d", &startx, &starty, &p, &q);

    book[startx][starty] = 1;

    dfs(startx, starty, 0);

    printf("%d", min);

    return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值