uva 532 Dungeon Master —— BFS(求最短路)

使用BFS进行正确的求解:

/**
序号:num_7
作者:MrZhang
日期:2016-5-26


题目名称: Dungeon Master(逃离地牢)
题目来源:
uva —— 532 —— Dungeon Master
网址:
英文题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19489
--------------------------------------
数据样例:
input:

3 4 5
S....
.###.
.##..
###.#
#####
#####
##.##
##...
#####
#####
#.###
####E
1 3 3
S##
#E#
###
0 0 0

output

Escaped in 11 minute(s).
Trapped!
*/

#include <iostream>
#include <cstring>
#include <queue>
#define maxn 31

using namespace std;

typedef struct node{
    int l;
    int r;
    int c;
}Node;

int L,R,C;
char G[maxn][maxn][maxn];
int visited[maxn][maxn][maxn];
int dist[maxn][maxn][maxn];
Node start_node;
queue<Node> q;

int INF = 27100;//!因为30*30*30,最多有27000的长度。
bool successed;
int _time;//!注意不能命名为"time",原因不明。否则将出现错误:cannot convert 'int' to 'time_t(time_t*) throw () {aka long int(long int*) throw ()}

bool check(int l,int r,int c){
    if(l >= 0 && l <= L-1 && r >= 0 && r <= R-1 && c >= 0 && c <= C-1){
        if((G[l][r][c] == '.' || G[l][r][c] == 'E')  && !visited[l][r][c]){
            return true;
        }
    }

    return false;
}

//!         前后左右上下
int dL[8] = { 0,0,  0,0,  1,-1};
int dR[8] = {-1,1,  0,0,  0, 0};
int dC[8] = { 0,0, -1,1,  0, 0};

void bfs(){
    visited[start_node.l][start_node.r][start_node.c] = 1;
    dist[start_node.l][start_node.r][start_node.c] = 0;
    q.push(start_node);

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

        for(int i = 0; i < 6;i ++){
            int l2 = u.l + dL[i];
            int r2 = u.r + dR[i];
            int c2 = u.c + dC[i];

             if(check(l2,r2,c2)){
                visited[l2][r2][c2] = 1;
                dist[l2][r2][c2] = dist[u.l][u.r][u.c] + 1;

                if(G[l2][r2][c2] == 'E'){
                    successed = true;
                    _time = dist[l2][r2][c2];
                    return ;
                }

                Node v;
                v.l = l2; v.r = r2; v.c = c2;
                q.push(v);
            }

        }

    }
}

void input(){
    memset(G,'#',sizeof(G));
    memset(visited,0,sizeof(visited));
    memset(dist,0,sizeof(dist));
    while(!q.empty()) q.pop();

    successed = false;
    _time = INF;

    for(int l = 0; l < L; l++){//层数
        for(int r = 0; r < R; r ++){//行数
            for(int c = 0; c < C; c ++){//列数
                cin>>G[l][r][c];

                if(G[l][r][c] == 'S'){
                    start_node.l = l;
                    start_node.r = r;
                    start_node.c = c;
                }
            }
        }
    }
}

int main(){
    while(cin>>L>>R>>C){
        if(!L&&!R&&!C) break;

        input();

        bfs();

        if(successed){
            cout<<"Escaped in "<<_time<<" minute(s)."<<endl;
        }else{
            cout<<"Trapped!"<<endl;
        }
    }

    return 0;
}
/**
总结:
题型:  图的遍历 + 最短路
     ————三维立体图的遍历
原理:BFS(宽度优先搜索)

注意:
   对这一种有某个目的点的问题,在写check()时,终点也是可以通行的点。

补充:针对最短路问题的理解:
求最短路时应使用bfs,以宽度优先进行搜索。
*/


附上使用DFS的错误示例,结果正确,但是超时(Time Limited error)。

/**
错误示例:
原理:DFS。
结果:结果是正确的,但是超时(Time limited error)。
*/
#include <iostream>
#include <cstring>

#define maxn 31

using namespace std;
char G[maxn][maxn][maxn];
int visited[maxn][maxn][maxn];
int L,R,C;

int INF = 27100;//!因为30*30*30,最多有27000的长度。

bool successed;
int _time;//!注意不能命名为"time",原因不明。否则将出现错误:cannot convert 'int' to 'time_t(time_t*) throw () {aka long int(long int*) throw ()}
int nowTime;
int s_L,s_R,s_C;

bool check(int l,int r,int c){
    if(l >= 0 && l <= L-1 && r >= 0 && r <= R-1 && c >= 0 && c <= C-1){
        if((G[l][r][c] == '.' || G[l][r][c] == 'E')  && !visited[l][r][c]){
            if(nowTime < _time) return true;
        }
    }

    return false;
}
//!         前后左右上下
int dL[8] = { 0,0,  0,0,  1,-1};
int dR[8] = {-1,1,  0,0,  0, 0};
int dC[8] = { 0,0, -1,1,  0, 0};

void dfs(int l,int r,int c){
    if(G[l][r][c] == 'E'){
        successed = true;
        if(nowTime < _time) _time = nowTime;

        return ;
    }

    for(int i = 0; i < 6;i ++){
        int l2 = l + dL[i];
        int r2 = r + dR[i];
        int c2 = c + dC[i];

        if(check(l2,r2,c2)){
            visited[l2][r2][c2] = 1;
            nowTime ++;

            dfs(l2,r2,c2);

            visited[l2][r2][c2] = 0;
            nowTime --;
        }
    }
}

void input(){
    memset(G,'#',sizeof(G));
    memset(visited,0,sizeof(visited));

    successed = false;
    _time = INF;
    nowTime = 0;

    for(int l = 0; l < L; l++){//层数
        for(int r = 0; r < R; r ++){//行数
            for(int c = 0; c < C; c ++){//列数
                cin>>G[l][r][c];

                if(G[l][r][c] == 'S'){
                    s_L = l;
                    s_R = r;
                    s_C = c;
                }
            }
        }
    }

}

int main(){
    while(cin>>L>>R>>C){
        if(!L&&!R&&!C) break;

        input();

        dfs(s_L,s_R,s_C);

        if(successed){
            cout<<"Escaped in "<<_time<<" minute(s)."<<endl;
        }else{
            cout<<"Trapped!"<<endl;
        }
    }

    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张之海

若有帮助,客官打赏一分吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值