我是流氓,我怕谁!

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 }
View Code

 

注意到之后,那么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 }
View Code

 

 

posted @ 2014-06-30 12:13  江忻玺  阅读(160)  评论(0编辑  收藏  举报