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

 

转载于:https://www.cnblogs.com/luyingfeng/p/3254722.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值