POJ3083Children of the Candy Corn

题意:给你一个迷宫,入口处标为S,出口处标为E,可以走的地方为“.”,不可以走的地方为#,求左转优先时从出口到入口的路程,再求右转优先时,出口到入口的路程,最后求从出口到入口的最短路程。

思路:求前两个的时候用DFS递归求解能走的路就OK,求最短的时候当然要用广度优先搜索啦。

  1 #include<cstdio>

  2 #include<cstring>

  3 #include<iostream>

  4 using namespace std ;

  5 char ch[158][158];

  6 int sum ;//总步数

  7 int h,w,i,j,k ;

  8 int enx,eny,stax,stay;

  9 int fx[] = {0,1,0,-1};//列的变化,从0开始顺时针变化

 10 int fy[] = {1,0,-1,0};//行的变化,从0开始顺时针变化

 11 int lef[] = {1,0,3,2};//左转优先时,标记上下左右4个方向分别为0213;

 12 int rig[] = {3,0,1,2};//右转优先时,右边为1;

 13 struct node

 14 {

 15     int xz,yz;

 16     int cnt;

 17 } sh[10001];//数组模拟队列

 18 void DFS(int dire,int x,int y,int d)//这个点的初始方向,这个点现在坐标,以及是左先还是右先

 19 {

 20     if(x == enx&&y == eny)//如果遍历到了'E'所在坐标,就结束掉遍历,返回

 21     {

 22         printf("%d",sum);

 23         return ;

 24     }

 25     int xx,yy;

 26     sum++;

 27     if(d == 1)//左转优先

 28     {

 29         for(i = 0 ; i <= 3 ; i++)//4个方向遍历一遍

 30         {

 31             j = (dire+lef[i])%4;//求出当前位置的方向数字

 32             xx = x+fx[j];//传过来的参数x为原来的坐标j

 33             yy = y+fy[j];

 34             if(xx>=0&&xx< h&&yy>=0&&yy< w&&ch[yy][xx] != '#')//继续遍历的条件是不为#且没越出边界,要注意xx是到h为边界的与主函数中对应

 35             {

 36                 DFS(j,xx,yy,1);//继续递归下去

 37                 return ;

 38             }

 39         }

 40     }

 41     else

 42     {

 43         for(i = 0 ; i <= 3 ; i++)

 44         {

 45             j = (dire+rig[i])%4;

 46             xx = x+fx[j];

 47             yy = y+fy[j];

 48             if(xx>=0 && xx < h&&yy>=0 && yy < w&&ch[yy][xx] != '#')

 49             {

 50                 DFS(j,xx,yy,0);

 51                 return ;

 52             }

 53         }

 54     }

 55 }

 56 void BFS(int x,int y)//广度优先搜索是队列,深度优先搜索是栈,深度是递归

 57 {

 58     int zh[158][158] = {0};//标记数组,初始化为0,表示节点未被访问过

 59     int le = 0,ri = 1 ;

 60     zh[y][x] = 1;

 61     //将当前点坐标压入队列,后边进行处理

 62     sh[0].xz = x;

 63     sh[0].yz = y ;

 64     sh[0].cnt = 1 ;

 65     while(le < ri)

 66     {

 67         x = sh[le].xz;//从队列中取出进行操作

 68         y = sh[le].yz ;

 69         sum = sh[le++].cnt;

 70         for(k = 0 ; k <= 3 ; k++)

 71         {

 72             //点的坐标

 73             i = y+fy[k];

 74             j = x+fx[k];

 75             if(i>=0 && i<w && j<h && j>=0 && !zh[i][j] &&ch[i][j]!='#')//在原有条件下,还要保证节点没有被访问过

 76             {

 77                 if(j == enx&&i == eny)//如果找到'E'就输出长度

 78                 {

 79                     cout<<sum+1<<endl;

 80                     return ;

 81                 }

 82                 zh[i][j] = 1;//表示这个节点已经被访问过了,标记为1

 83                 //将这个点加入队列用来以后进行访问这个点四周的点

 84                 sh[ri].yz = i;

 85                 sh[ri].xz = j;

 86                 sh[ri].cnt = sum+1;//这个点步数加1

 87                 ri++;//while循环结束的条件就是该点不符合条件,ri不再累加

 88             }

 89         }

 90     }

 91 }

 92 int main()

 93 {

 94     int n,dire;

 95     scanf("%d",&n);

 96     while(n--)

 97     {

 98         scanf("%d %d",&h,&w);//h是列,w是行

 99         for(i = 0 ; i <= w-1 ; i++)

100         {

101             scanf("%s",ch[i]);

102             for(j = 0 ; j <= h-1 ; j++)

103             {

104                 if(ch[i][j] == 'S')

105                 {

106                     stax = j;

107                     stay = i;

108                 }

109                 if(ch[i][j] == 'E')

110                 {

111                     enx = j;

112                     eny = i ;

113                 }

114             }

115         }

116         if(stax == 0) dire = 1;//

117         if(stax == h-1) dire = 3;//

118         if(stay == 0) dire = 0;//

119         if(stay == w-1) dire = 2 ;//

120         sum = 1;//初始化

121         DFS(dire,stax,stay,1);//左转优先

122         printf(" ");

123         sum = 1 ;//初始化

124         DFS(dire,stax,stay,0);//右转优先

125         printf(" ");

126         BFS(stax,stay);//求最短的用bfs

127     }

128     return 0;

129 }
View Code

 

你可能感兴趣的:(children)