Tempter of the Bone(深搜+一点点剪枝)

本文介绍了一个迷宫寻宝的算法问题,通过深度优先搜索(DFS)结合剪枝策略,解决小明在限定时间内从迷宫起点到达终点的问题。文章详细解析了代码实现过程,包括状态转移、边界条件和优化技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述
暑假的时候,小明和朋友去迷宫中寻宝。然而,当他拿到宝贝时,迷宫开始剧烈震动,他感到地面正在下沉,他们意识到这是一个陷阱!他们想尽一切办法逃出去。
迷宫是一个大小为 N*M 的长方形,迷宫中有一扇门。一开始,门是关着的,他会在第 t 秒的时间打开。因为,小明和朋友必须在第 t 秒到大门口。每一秒,他都可以向上下左右四个方向移动一个点。一旦他移动了,他刚才所在的点就消失,(这意味着他不能回到他已经走过的点)。他不能在一个点上停留超过一秒,并且不能走障碍点。小明和朋友能安全的逃出吗?
输入描述
输入由多个测试用例组成。每个测试用例的第一行包含三个整数 N、M 和 T ( 1 < N , M < 7 ; 0 < T < 50 ),分别表示迷宫的大小和门打开的时间。接下来的N行给出迷宫布局,每一行包含M个字符。下列字母分别表示:

“X”: 一堵墙,小明和朋友不能在上面停留
“S”: 起点
“D”: 门
“.”: 可以走的点
输入以 3 个 0 时结束。这个测试用例不需要处理。
输出描述
对于每组样例输出一行。
如果小明能够安全逃出,输出 “YES” ,否则输出 “NO”。
样例输入
4 4 5
S.X.
…X.
…XD

3 4 5
代码实现

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <math.h>
using namespace std;
char map[10][10];
int vis[20][20];
int N,M,T,ex,ey,flag;
int mov[4][2]= {-1,0,1,0,0,1,0,-1}; //方向数组
void dfs(int sx,int sy,int step)
{
    int i,next_x,next_y;
    if(flag)//很重要,可以减少步骤,也是如何使一旦找到需要的路线就可以连续return
        return;
    if(sx==ex &&sy==ey && step==T)
    {
        flag=1;
        return;
    }
    int tem=T-step-abs(ex-sx)-abs(ey-sy);//剪枝的核心代码
    if(tem<0||tem&1)//剪枝:如果剩余的步数已经不足以走到出口,且必须是偶数,偶数-偶数=偶数,奇数-奇数=偶数,
        return;
    for(i=0; i<4; i++)
    {
        next_x=sx+mov[i][0];
        next_y=sy+mov[i][1];
        if(next_x<0 || next_y>=M || next_y<0 || next_x>=N)
            continue;
        if(map[next_x][next_y]!='X' && vis[next_x][next_y]==0)
        {
            vis[next_x][next_y]=1;//及时标记,先判断后标记,先确定能不能走 ,在考虑走完标记的问题
            dfs(next_x,next_y,step+1);
            if(flag)//若找到结果,及时return
                return;
            vis[next_x][next_y]=0;//注意返回标记 以便下次搜索
        }
    }
    return ;
}
int main()
{
    int i,j,wall;
    int sx,sy;
    while(~scanf("%d %d %d",&N,&M,&T))
    {
        if(N==0 && M==0 && T==0)
            break;
        flag=0;
        wall=0;
        memset(vis,0,sizeof(vis));
        for(i=0; i<N; i++)
        {
            scanf("%s",map[i]);
        }
        for(i=0; i<N; i++)
        {
            for(j=0; j<M; j++)
            {
                if(map[i][j]=='S')
                {
                    sx=i;
                    sy=j;
                }
                if(map[i][j]=='D')
                {
                    ex=i;
                    ey=j;
                }
                if(map[i][j]=='X')
                    wall++;
            }
        }
        if(T>N*M-wall-1)//注意时间与墙数和地图的数量关系会减少很多步骤哦
        {
            printf("NO\n");
            continue;
        }
        vis[sx][sy]=1;//务必记得标记走过的路径
        dfs(sx,sy,0);
        if(flag==1)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值