码迷,mamicode.com
首页 > 其他好文 > 详细

关于【广度优先搜索】

时间:2014-11-12 19:22:12      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:style   blog   io   color   ar   os   sp   for   strong   

 

题目1456:胜利大逃亡

题目描述:

Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会.魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius被关在(0,0,0)的位置,离开城堡的门在(A-1,B-1,C-1)的位置,现在知道魔王将在T分钟后回到城堡,Ignatius每分钟能从一个坐标走到相邻的六个坐标中的其中一个.现在给你城堡的地图,请你计算出Ignatius能否在魔王回来前离开城堡(只要走到出口就算离开城堡,如果走到出口的时候魔王刚好回来也算逃亡成功),如果可以请输出需要多少分钟才能离开,如果不能则输出-1.

输入:

输入数据的第一行是一个正整数K,表明测试数据的数量.每组测试数据的第一行是四个正整数A,B,C和T(1<=A,B,C<=50,1<=T<=1000),它们分别代表城堡的大小和魔王回来的时间.然后是A块输入数据(先是第0块,然后是第1块,第2块......),每块输入数据有B行,每行有C个正整数,代表迷宫的布局,其中0代表路,1代表墙。

输出:

对于每组测试数据,如果Ignatius能够在魔王回来前离开城堡,那么请输出他最少需要多少分钟,否则输出-1.

样例输入:
1
3 3 4 20
0 1 1 1
0 0 1 1
0 1 1 1
1 1 1 1
1 0 0 1
0 1 1 1
0 0 0 0
0 1 1 0
0 1 1 0 
样例输出:
11

代码如下:

#include <iostream>
#include <stdio.h>
#include <queue>
 
using namespace std;
 
/*所谓广度优先搜索,即在遍历解答树时使每次状态转移时扩展出尽可能多
的新状态,并且按照各个状态出现的先后顺序依次扩展它们。但是,这样所
需查找的状态是非常多,最坏情况下,因为每个结点都能扩展出6个新结点,
那么仅走10步,其状态数就会达到6^10,需要大量的时间才能依次遍历完这
些状态,所以我们必须采用相应的措施来制约状态的无限扩展,这个方法就
是剪枝*/
 
/*在起点走向终点的最短路径上,到达任意一个中间结点所用的时间都是起
点到达这个结点的最短时间,那么我们所要查找的答案比不可能由该状态进
行若干次扩展后得到*/
 
/*例如:当我们第一次查找到包含点(x,y,z)的坐标状态后,其后查找到的
任意包含该坐标的状态都不必扩展*/
 
bool mark[50][50][50];  //标记数组
int maze[50][50][50];   //保存立方体信息
 
struct N{
    int x;
    int y;
    int z;
    int t;
};
 
queue<N> Q;            //队列,队列中的元素为状态
int go[][3]={          //坐标变换数组,由坐标(x,y,z)扩展得到的新坐标均可
        {1,0,0},       //通过(x+go[i][0],y+go[i][1],z+go[i][2])得到
        {-1,0,0},
        {0,1,0},
        {0,-1,0},
        {0,0,1},
        {0,0,-1}
        };
 
int BFS(int a,int b,int c){    //广度优先搜索,返回其最少耗时
    while(Q.empty()==false){   //当队列中仍有元素可以扩展时循环
        N now=Q.front();       //得到队头状态
        Q.pop();               //从队列中弹出队头状态
        for(int i=0;i<6;i++){  //依次扩展其6个相邻结点
            int nx=now.x+go[i][0];
            int ny=now.y+go[i][1];
            int nz=now.z+go[i][2];
            if(nx<0||nx>=a||ny<0||ny>=b||nz<0||nz>=c)  //若新坐标在立方体外,则丢弃该坐标
                continue;
            if(maze[nx][ny][nz]==1)     //若该位置为墙,则丢弃该坐标
                continue;
            if(mark[nx][ny][nz]==true)  //若包含该坐标的状态已经被得到过,则丢弃该状态
                continue;
            N temp;                     //新的状态
            temp.x=nx;
            temp.y=ny;
            temp.z=nz;                  //新状态包含的坐标
            temp.t=now.t+1;             //新状态的耗时
            Q.push(temp);               //将新状态加入到队列
            mark[nx][ny][nz]=true;      //标记该坐标
            if(nx==a-1&&ny==b-1&&nz==c-1)
                return temp.t;
        }
    }
    return -1;
}
 
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int a,b,c,t;
        scanf("%d%d%d%d",&a,&b,&c,&t);     //输入
        for(int i=0;i<a;i++){
            for(int j=0;j<b;j++){
                for(int k=0;k<c;k++){
                    scanf("%d",&maze[i][j][k]);      //输入立方体信息
                    mark[i][j][k]=false;             //初始化标记数组
                }
            }
        }
        while(Q.empty()==false)          //清空队列
            Q.pop();
        mark[0][0][0]=true;              //标记起点
        N temp;
        temp.x=temp.y=temp.z=temp.t=0;   //初始状态
        Q.push(temp);                    //将初始状态放入队列
        int rec=BFS(a,b,c);              //广度优先搜索
        if(rec<=t)
            printf("%d\n",rec);          //若所需时间符合条件,则输出
        else
            printf("-1\n");              //否则输出-1
    }
    return 0;
}
 
/**************************************************************
    Problem: 1456
    User: lcyvino
    Language: C++
    Result: Accepted
    Time:30 ms
    Memory:2132 kb
****************************************************************/

 

关于【广度优先搜索】

标签:style   blog   io   color   ar   os   sp   for   strong   

原文地址:http://www.cnblogs.com/Murcielago/p/4092941.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!