深搜和广搜

Dungeon Master

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 58498 Accepted: 21525

Description

You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot move diagonally and the maze is surrounded by solid rock on all sides. 

Is an escape possible? If yes, how long will it take? 

Input

The input consists of a number of dungeons. Each dungeon description starts with a line containing three integers L, R and C (all limited to 30 in size). 
L is the number of levels making up the dungeon. 
R and C are the number of rows and columns making up the plan of each level. 
Then there will follow L blocks of R lines each containing C characters. Each character describes one cell of the dungeon. A cell full of rock is indicated by a '#' and empty cells are represented by a '.'. Your starting position is indicated by 'S' and the exit by the letter 'E'. There's a single blank line after each level. Input is terminated by three zeroes for L, R and C.

Output

Each maze generates one line of output. If it is possible to reach the exit, print a line of the form 

Escaped in x minute(s).


where x is replaced by the shortest time it takes to escape. 
If it is not possible to escape, print the line 

Trapped!

Sample Input

3 4 5
S....
.###.
.##..
###.#

#####
#####
##.##
##...

#####
#####
#.###
####E

1 3 3
S##
#E#
###

0 0 0

Sample Output

Escaped in 11 minute(s).
Trapped!

Source

Ulm Local 1997

深搜只是确定它是否存在;(深搜时间复杂度远远大于广搜,所以一般找到结果之后都会选择直接退出)

广搜才是确定它的最短路径;

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int vis[36][36][36];
int ans;
char tu[36][36][36];
int l,r,c;
int flag;
int cnt;
int zhong;
int movee[19]= {0, 0,1,0, 0,-1,0, 0,0,1, 0,0,-1, 1,0,0, -1,0,0 };
//1 (1)   4(2)     7(3)    10(4)    13(5)    16(6)

void in(int high,int x,int y)
{
    if(tu[high][x][y]=='E' && cnt < zhong)
    {
        zhong=cnt;
        ans=cnt;
        return;
    }
    else
    {
        for(int i=1; i<=16; i=i+3)
        {

            high=high+movee[i];
            x=x+movee[i+1];
            y=y+movee[i+2];

            if( ( tu[high][x][y]=='.' || tu[high][x][y]=='E' ) && vis[high][x][y]==0 && high>=1 && high<=l && x>=1 && x<=r &&y>=1 &&y<=c )
            {

                vis[high][x][y]=1;
                cnt++;

                in(high,x,y);

                cnt--;
                vis[high][x][y]=0;
            }
            high=high-movee[i];
            x=x-movee[i+1];
            y=y-movee[i+2];

        }
    }
    return;
}


int main()
{

    while((cin>>l>>r>>c) && l && r &&c)
    {
        memset(vis,0,sizeof(vis));
        cnt=0;
        int high,x,y;
        int high_end,x_end,y_end;
        ans=0;
        zhong=0x3f3f3f;

        for(int i=1; i<=l; i++)
        {
            for(int j=1; j<=r; j++)
            {
                for(int k=1; k<=c; k++)
                {
                    cin>>tu[i][j][k];

                    if( tu[i][j][k]=='S' )
                    {
                        high=i;
                        x=j;
                        y=k;
                        //cout<<i<<j<<k<<endl;
                    }
                    if( tu[i][j][k]=='E' )
                    {
                        high_end=i;
                        x_end=j;
                        y_end=k;
                    }
                }

            }

        }
        vis[high][x][y]=1;
        in(high,x,y);
        if(ans)
        {
           printf("Escaped in %d minute(s).\n",ans);
        }
        else
        {
           printf("Trapped!\n");
        }


    }


}

 

#include<stdio.h>
#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
char map[30][30][30];        //记录节点信息
int vis[30][30][30];        //标记是否访问

int base[6][3] = { {-1,0,0},{1,0,0},{0,-1,0},{0,1,0},{0,0,-1},{0,0,1} };

int L, R, C;

typedef struct
{
    int x, y, z;            //位置坐标
    int step;                //出发点到该点的步数
} node;

node s;                //起点
node e;                //终点
node curp;             //跳出循环时的节点


bool success(node cur)
{
    if (cur.x == e.x  &&  cur.y == e.y && cur.z == e.z)
        return true;
    else
        return false;
}


bool check(int x, int y, int z)
{
    if ( (x >= 0) && (x < L) && (y >= 0) && (y < R) && (z >= 0) && (z < C) && (!vis[x][y][z]) && (map[x][y][z] == '.' || map[x][y][z] == 'E'))
        return true;
    else
        return false;
}


void bfs()
{

    queue<node> q;
    q.push(s);

    while (!q.empty())
    {
        curp = q.front();
        q.pop();

        if ( success(curp) )
            return;

        else
        {
            vis[curp.x][curp.y][curp.z] = 1;

            node next;
            for (int i = 0; i < 6; i++)
            {
                next.x = curp.x + base[i][0];
                next.y = curp.y + base[i][1];
                next.z = curp.z + base[i][2];

                if ( check(next.x, next.y, next.z) )        //扩展队列
                {
                    next.step = curp.step + 1;
                    vis[next.x][next.y][next.z] = 1;

                    q.push(next);

                }
            }
        }
    }
}
int main()
{
    while (scanf("%d%d%d", &L, &R, &C))
    {
        if((L == 0) && (R == 0) && (C == 0))
            break;

        memset(vis, 0, sizeof(vis));

        for (int i = 0; i < L; i++)
        {
            for (int j = 0; j < R; j++)
            {
                for (int k = 0; k < C; k++)
                {
                    cin>>map[i][j][k];
                    if (map[i][j][k] == 'S')
                    {
                        s.x = i;
                        s.y = j;
                        s.z = k;
                        s.step = 0;
                    }
                    else if (map[i][j][k] == 'E')
                    {
                        e.x = i;
                        e.y = j;
                        e.z = k;
                    }
                }

            }
        }

        bfs();
        if ( curp.x == e.x && curp.y == e.y && curp.z == e.z )
            printf("Escaped in %d minute(s).\n", curp.step);
        else
            printf("Trapped!\n");
    }
    return 0;
}

 

### 度优先索与广度优先索中的剪枝技术 #### 度优先索 (DFS) 中的剪枝技术 度优先索是一种沿着某个方向尽可能入探索节点的策略。然而,在实际应用中,可能会遇到大量的无意义路径或冗余计算。为了提高效率,可以通过剪枝来减少不必要的分支。 剪枝的核心思想是在索过程中提前判断某些子树是否可能包含目标解,如果不可能,则跳过这些子树的进一步扩展。例如,在解决约束满足问题时,可以利用当前状态下的约束条件排除那些无法满足最终解的状态[^1]。 以下是 DFS 的基本框架以及如何加入剪枝逻辑: ```python def dfs(node, visited): if is_invalid_state(node): # 判断当前状态是否无效(剪枝) return False if is_goal(node): # 如果找到目标则返回成功 return True visited.add(node) for neighbor in get_neighbors(node): if neighbor not in visited: if dfs(neighbor, visited): # 继续递归索邻居节点 return True return False ``` 在此代码片段中,`is_invalid_state()` 函数用于检测当前节点是否违反任何已知规则或约束条件。一旦发现不可行的情况即可立即停止对该分支的继续探索[^2]。 --- #### 广度优先索 (BFS) 中的剪枝技术 相比 DFS,广度优先索按层展开索空间,通常适用于寻找最短路径等问题。尽管 BFS 能够提供最优解,但在大规模数据集上其内存消耗较高。因此引入剪枝同样有助于提升性能并降低资源占用。 对于 BFS 来说,常见的剪枝方法包括但不限于以下几种方式: - **启发式估计**:通过估算剩余距离或其他指标决定哪些候选项更值得保留; - **重复状态过滤**:避免多次访问相同的状态从而节省时间开销; - **边界限制设置**:只考虑一定范围内的可能性而忽略超出部分。 下面是一个带有简单剪枝机制的 BFS 示例程序: ```python from collections import deque def bfs(start_node): queue = deque([start_node]) visited = set() while queue: node = queue.popleft() if is_invalid_state(node): # 对于不符合条件的状态直接丢弃 continue if is_goal(node): # 找到解决方案即刻终止循环 break visited.add(node) neighbors = get_neighbors(node) for n in neighbors: if n not in visited and meets_pruning_criteria(n): # 只有符合条件的新邻接点才会被加入队列 queue.append(n) return None if not found_solution else solution_path ``` 这里 `meets_pruning_criteria()` 是一个自定义函数用来评估每一个候选者是否应该进入下一步处理阶段。 --- #### 总结比较两者差异及适用场景 | 特性 | 度优先索 | 广度优先索 | |--------------------|---------------------------------------|--------------------------------------| | 探索顺序 | 向下逐级入 | 层次化横向扫描 | | 存储需求 | 较低 | 高 | | 是否保证最佳答案 | 不一定 | 当存在单位权重边时可获得最小步数解答| 无论采用哪种基础算法形式,合理运用剪枝技巧都能够显著改善整体表现效果。值得注意的是具体实施方案需依据实际情况灵活调整以达到理想成效。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值