poj2251:Dungeon Master

最初没有注意到结果是要求最小的步数,那么就成了最基本的迷宫找到一条出路的问题并记下找到出路时,所花的步数,那么很容易得到代码如下:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 using namespace std;
  5
  6 #define MAX 1000000
  7 int l,r,c,coun;
  8 char m[30][30][30];
  9 bool flag[30][30][30];
 10 int num[30][30][30]={0};
 11 void work(int i,int j,int level,int mins)
 12 {
 13     //flag[level][i][j] = false;
 14     num[level][i][j] = mins;
 15     if(mins >= coun)
 16         return ;
 17     if(m[level][i][j] == ‘E‘)
 18     {
 19         coun = mins;
 20         return ;
 21     }
 22
 23     if(level < l-1)
 24     {
 25         if((flag[level+1][i][j] == true) && (num[level+1][i][j] == 0 || mins+1 < num[level+1][i][j]))
 26             work(i,j,level+1,mins+1);
 27     }
 28     if(level > 0)
 29     {
 30         if(flag[level-1][i][j] == true&& (num[level-1][i][j] == 0 || mins+1 < num[level-1][i][j]))
 31             work(i,j,level-1,mins+1);
 32     }
 33     if(i < r-1)
 34     {
 35         if(flag[level][i+1][j] == true&& (num[level][i+1][j] == 0 || mins+1 < num[level][i+1][j]))
 36             work(i+1,j,level,mins+1);
 37     }
 38     if(i > 0)
 39     {
 40         if(flag[level][i-1][j] == true&& (num[level][i-1][j] == 0 || mins+1 < num[level][i-1][j]))
 41             work(i-1,j,level,mins+1);
 42     }
 43     if(j < c-1)
 44     {
 45         if(flag[level][i][j+1] == true&& (num[level][i][j+1] == 0 || mins+1 < num[level][i][j+1]))
 46             work(i,j+1,level,mins+1);
 47     }
 48     if(j > 0)
 49     {
 50         if(flag[level][i][j-1] == true&& (num[level][i][j-1] == 0 || mins+1 < num[level][i][j-1]))
 51             work(i,j-1,level,mins+1);
 52     }
 53 }
 54
 55 int main()
 56 {
 57     while(cin>>l>>r>>c)
 58     {
 59         if(l == 0 && r == 0 && c == 0)
 60             break;
 61         int startl,starti,startj;
 62         char s;
 63         scanf("%c",&s);
 64         for(int i = 0; i < l; i++ )
 65         {
 66             for(int j = 0; j < r; j++)
 67             {
 68                 for(int k = 0; k < c; k++)
 69                 {
 70                     scanf("%c",&m[i][j][k]);
 71                     if(m[i][j][k] == ‘S‘)
 72                     {
 73                         startl = i;
 74                         starti = j;
 75                         startj = k;
 76                     }
 77                     if(m[i][j][k] == ‘#‘)
 78                         flag[i][j][k] = false;
 79                     else
 80                         flag[i][j][k] = true;
 81                 }
 82                 scanf("%c",&s);
 83             }
 84             scanf("%c",&s);
 85         }
 86         /*for(int i = 0; i < l; i++ )
 87          {
 88          for(int j = 0; j < r; j++)
 89          {
 90          for(int k = 0; k < c; k++)
 91          {
 92          printf("%c",m[i][j][k]);
 93          }
 94          printf("\n");
 95          }
 96          printf("\n");
 97          }*/
 98         coun = MAX;
 99         memset(num,0,sizeof(num));
100         work(starti,startj,startl,0);
101         if(coun < MAX)
102             printf("Escaped in %d minute(s).\n", coun);
103         else
104             printf("Trapped!\n");
105     }
106     return 0;
107 }

注意到之后,那么bool 属性的flag其实就不必了,我在下文代码中的flag其实只是用来判断那个点是否是‘#’字符而已,没什么用,必须遍历所有情况才能够找出最小步数,那么就只需要剪枝就好了。

最开始,我注意到的剪枝方法就是最简单的,只有一个返回条件:

1.当前的步数已经超过最小的通过迷宫的步数的时候,返回。

结果发现无限循环了。。。想了一想,因为并没有限制重复的搜索,所以一直在无限制的重复搜索下去了。

那么加上第二个剪枝条件来防止无限制地重复搜索:

2.当下一步要访问的点之前已经访问过的时候,而且如果要访问的话,之前访问到该点的步数小于或者等于当前情况访问到该点的步数,则不再去访问。

按照这个思路,写完代码提交过后,又出现了超时。。。

则加上第三个剪枝条件,实质上是加强了第一个条件:

当前访问到的点已经经过的步数加上到达出口所需的最短步数已经超过 之前计算出的通过迷宫所需的最短步数时,则返回。

终于AC了!现在献上AC代码

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <math.h>
  5 #include <stdlib.h>
  6 using namespace std;
  7
  8 #define MAX 1000000
  9 int l,r,c,coun;
 10 char m[30][30][30];
 11 bool flag[30][30][30];
 12 int num[30][30][30]={0};
 13 int startl,starti,startj,endle,endi,endj;
 14 void work(int i,int j,int level,int mins)
 15 {
 16     //flag[level][i][j] = false;
 17     num[level][i][j] = mins;
 18     if(mins+abs(i-endi)+abs(j-endj)+abs(level-endle) >= coun)
 19         return ;
 20     if(m[level][i][j] == ‘E‘)
 21     {
 22         coun = mins;
 23         return ;
 24     }
 25
 26     if(level < l-1)
 27     {
 28         if((flag[level+1][i][j] == true) && (num[level+1][i][j] == 0 || mins+1 < num[level+1][i][j]))
 29             work(i,j,level+1,mins+1);
 30     }
 31     if(level > 0)
 32     {
 33         if(flag[level-1][i][j] == true&& (num[level-1][i][j] == 0 || mins+1 < num[level-1][i][j]))
 34             work(i,j,level-1,mins+1);
 35     }
 36     if(i < r-1)
 37     {
 38         if(flag[level][i+1][j] == true&& (num[level][i+1][j] == 0 || mins+1 < num[level][i+1][j]))
 39             work(i+1,j,level,mins+1);
 40     }
 41     if(i > 0)
 42     {
 43         if(flag[level][i-1][j] == true&& (num[level][i-1][j] == 0 || mins+1 < num[level][i-1][j]))
 44             work(i-1,j,level,mins+1);
 45     }
 46     if(j < c-1)
 47     {
 48         if(flag[level][i][j+1] == true&& (num[level][i][j+1] == 0 || mins+1 < num[level][i][j+1]))
 49             work(i,j+1,level,mins+1);
 50     }
 51     if(j > 0)
 52     {
 53         if(flag[level][i][j-1] == true&& (num[level][i][j-1] == 0 || mins+1 < num[level][i][j-1]))
 54             work(i,j-1,level,mins+1);
 55     }
 56 }
 57
 58 int main()
 59 {
 60     while(cin>>l>>r>>c)
 61     {
 62         if(l == 0 && r == 0 && c == 0)
 63             break;
 64
 65         char s;
 66         scanf("%c",&s);
 67         for(int i = 0; i < l; i++ )
 68         {
 69             for(int j = 0; j < r; j++)
 70             {
 71                 for(int k = 0; k < c; k++)
 72                 {
 73                     scanf("%c",&m[i][j][k]);
 74                     if(m[i][j][k] == ‘S‘)
 75                     {
 76                         startl = i;
 77                         starti = j;
 78                         startj = k;
 79                     }
 80                     if(m[i][j][k] == ‘E‘)
 81                     {
 82                         endle = i;
 83                         endi = j;
 84                         endj = k;
 85                     }
 86                     if(m[i][j][k] == ‘#‘)
 87                         flag[i][j][k] = false;
 88                     else
 89                         flag[i][j][k] = true;
 90                 }
 91                 scanf("%c",&s);
 92             }
 93             scanf("%c",&s);
 94         }
 95         /*for(int i = 0; i < l; i++ )
 96          {
 97          for(int j = 0; j < r; j++)
 98          {
 99          for(int k = 0; k < c; k++)
100          {
101          printf("%c",m[i][j][k]);
102          }
103          printf("\n");
104          }
105          printf("\n");
106          }*/
107         coun = MAX;
108         memset(num,0,sizeof(num));
109         work(starti,startj,startl,0);
110         if(coun < MAX)
111             printf("Escaped in %d minute(s).\n", coun);
112         else
113             printf("Trapped!\n");
114     }
115     return 0;
116 }

poj2251:Dungeon Master,布布扣,bubuko.com

时间: 2024-10-12 07:30:04

poj2251:Dungeon Master的相关文章

POJ2251——Dungeon Master(三维BFS)

和迷宫问题区别不大,相比于POJ1321的棋盘问题,这里的BFS是三维的,即从4个方向变为6个方向. 用上队列的进出操作较为轻松. #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; char map[35][35][35]; int vis[35][35][35]; int t

hdu 2251 Dungeon Master bfs

Dungeon Master Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17555   Accepted: 6835 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

UVA532 Dungeon Master

问题链接:UVA532 Dungeon Master. 题意简述:三维空间地牢(迷宫),每个点由'.'(可以经过).'#'(墙).'S'(起点)和'E'(终点)组成.移动方向有上.下.左.右.前和后6个方向.每移动一次耗费1分钟,求从'S'到'E'最快走出时间.不同L层,相同RC处是连通的. 问题分析:一个三维迷宫,典型的BFS问题.在BFS搜索过程中,走过的点就不必再走了,因为这次再走下去不可能比上次的步数少. 程序中,使用了一个队列来存放中间节点,但是每次用完需要清空.需要注意的一点,为了编

POJ 2251 Dungeon Master --- 三维BFS(用BFS求最短路)

POJ 2251 题目大意: 给出一三维空间的地牢,要求求出由字符'S'到字符'E'的最短路径,移动方向可以是上,下,左,右,前,后,六个方向,每移动一次就耗费一分钟,要求输出最快的走出时间.不同L层的地图,相同RC坐标处是相连通的.(.可走,#为墙) 解题思路:从起点开始分别往6个方向进行BFS(即入队),并记录步数,直至队为空.若一直找不到,则困住. /* POJ 2251 Dungeon Master --- 三维BFS(用BFS求最短路) */ #include <cstdio> #i

poj 2251 Dungeon Master(优先队列bfs)

Dungeon Master Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20867   Accepted: 8090 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

ZOJ 1940 Dungeon Master 三维BFS

Dungeon Master Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u 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 r

UVA 532 Dungeon Master

题目如下: Dungeon Master  You are trapped in a 3D dungeon and need to find the quickest way out!The dungeon is composedof unit cubes which may or may not be filled with rock. It takes one minuteto move one unit north,south, east, west, up or down. You ca

POJ 2251 Dungeon Master(bfs)

Dungeon Master 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 dow

POJ:Dungeon Master(三维bfs模板题)

Dungeon Master Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16748   Accepted: 6522 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