数据结构之初试DFS(迷宫问题)

题目来自洛谷;

附上题目:迷宫问题

[1]题目

给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

输入格式

第一行N、M和T,N为行,M为列,T为障碍总数。第二行起点坐标SX,SY,终点坐标FX,FY。接下来T行,每行为障碍点的坐标。

输出格式

给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。

[2]输入输出样例:

输入#1

2 2 1

1 1 2 2

1 2

输出#1

1

输入#2

5 5 5
1 2 5 5
2 1
2 2
2 3
2 4
3 4

输出#2

10

[3]题解:

我用二维数组将走过的地方标记且用二维数组将障碍也标记了
这里可以用一个二维数组,也可以用两个
(为了可读性最好使用两个,当然也可以选择用一个二维数组但是不同的数字来标记)
当遇到障碍或撞到墙时返回
当找到终点时计数器加一

PS:

我遇到的问题(我蒟蒻,问题有点多):

  1. 输入忘记取地址符(这很傻,但就是出现了,而且我就被这个困了好久)
  2. 不在迷宫里面的条件是(next_x<=0||next_x>N||next_y<=0||next_y>M),一定要有等号;
  3. 需要在搜这个点之前将它备注为2(走过之后的标记)
  4. 回溯只需要在搜完这个点之后将它的状态改回最初的状态就可以了,需要注意的是,你要搜的点是你现在所搜点的下一个点,即,你的跳过,返回条件都是为下一个点准备的,都得基于下一个点 eg:if(next_x<=0||next_x>N||next_y<=0||next_y>M)是判断下一个点
  5.  开始我的回溯也出了错误,就我把    next_x=x-dir[i][0];next_y=y-dir[i][1];    错误理解为回溯了,人傻了

[3]代码:

//第一个

#include<stdio.h>
#include<stdlib.h>
int cout=0;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int sx,sy,fx,fy,Tx,Ty;
int N,M,T;
int map[100][100]={0};
//int way[100][100]={0};
void dfs(int x,int y)
{
    //到了终点,就让计数器cout+1
    if(x==fx&&y==fy)
    {
        cout++;
        return;
    }
    for(int i=0;i<4;i++)
    {
        int next_x=x+dir[i][0];
        int next_y=y+dir[i][1];
        //不在这个迷宫里面
        if(next_x<=0||next_x>N||next_y<=0||next_y>M)
            continue;
        //碰到障碍
        if(map[next_x][next_y]==1||map[next_x][next_y]==2)
            continue;
        map[next_x][next_y]=2;
        dfs(next_x,next_y);
        map[next_x][next_y]=0;
    }
    return;
}
int main()
{
    scanf("%d %d %d",&N,&M,&T);
    //起点和终点的坐标
    scanf("%d %d %d %d",&sx,&sy,&fx,&fy);
    for(int i=0;i<T;i++)
    {
        scanf("%d %d",&Tx,&Ty);
        //将障碍所处的位置记录下来
        map[Tx][Ty]=1;
    }
    map[sx][sy]=2;
    dfs(sx,sy);
    printf("%d\n",cout);
    return 0;
}

//第二个

#include<stdio.h>
int cout=0;
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
int sx,sy,fx,fy;
int N,M,T;
//当map[][]为0时就可以通行,为1时则为障碍不可通行
int map[100][100]={0};
//因为题目的要求就是“每个方格最多经过1次”
//way[][]这个二维数组用来记录这个(x,y)这个点是否走过
int way[100][100]={0};
void dfs(int x,int y)
{
    //到了终点,就让计数器cout+1(即,找到了一种方法)
    if(x==fx&&y==fy)
    {
        cout++;
        return;
    }
    for(int i=0; i<4; i++)
    {
        int next_x=x+dir[i][0];
        int next_y=y+dir[i][1];
        //在这个迷宫里面且没有碰到障碍才继续搜索
        if(next_x>0&&next_x<=N&&next_y>0&&next_y<=M&&map[next_x][next_y]==0&&way[next_x][next_y]==0)
        {
            way[next_x][next_y]=1;
            dfs(next_x,next_y);
            way[next_x][next_y]=0;
        }
    }
    return;
}
int main()
{
    scanf("%d %d %d",&N,&M,&T);
    //起点和终点的坐标
    scanf("%d %d %d %d",&sx,&sy,&fx,&fy);
    int Tx,Ty;
    for(int i=0; i<T; i++)
    {
        scanf("%d %d",&Tx,&Ty);
        //将障碍所处的位置记录下来
        map[Tx][Ty]=1;
    }
    way[sx][sy]=1;
    //从起点开始搜
    dfs(sx,sy);
    printf("%d\n",cout);
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值