杭电hdu 逃离迷宫

来源:互联网 发布:tw域名注册 编辑:程序博客网 时间:2024/05/21 17:18

写在前面的:
之前没有做过迷宫题目,所以先拿到题目想到的是dfs,因为很符合dfs的模型,要到达终点有很多步,每一步又有很多可能,但是,考虑到迷宫规格太大可能超时,而且还有拐弯
次数这个限制条件,所以不好处理。以前的国际象棋那个题目用了bfs,感觉差不多都是迷宫类型,所以决定用bfs试试。但是这个BFS是和普通的不同的,普通的是邻接定点入队列
但是这个却不是。


解题思路:
输入的话,输入地图的时候是按行读取到二维数组里面的。另外就是,题目是先输入列后输入行,要注意。之后就是进行bfs.每走一个点,这个点都应该包括三个数据,横纵
坐标还有在当前定点的时候的拐弯次数。我们要设当前所占的点为定点,然后向四个方向去扩展,也就是BFS,但是这里要注意的是,它的扩展是按照一个方向一次性搜到这个方向的底部
直到不能继续在搜索,然后再搜另外几个方向。因为题目当中有着拐弯次数这样的一个限制条件。搜索的时候,顶点的顺序是按照,拐弯次数为0,为1,这样以此类推的顺序向下搜索的。
因为从起点开始,我们设起点的拐弯次数为-1.因为从起点走到下一个扩展点是不需要转弯的,这一点是题目的限制条件。我们走的之后,每一次肯定要先走拐弯次数为0的,然后
再走为1,为2的,这也就造成了顶点入队列的时候的顺序有所不同。假设我现在从起点出来,所有拐弯次数为0的顶点都已经入队列,然后弹出一个,再进行四个方向的扩展搜索
把拐弯次数为1的部分顶点入队列。如果四个方向搜完之后都没搜到答案,那么再从队列头部弹出一个拐弯次数为0的点进行搜索,这样,能保证搜到正确答案的时候,走的路径也是最短的
BFS就是由这个特点。
关于剪枝,还是用的是记忆化搜索标记剪枝,遇到标记的之后,就证明这个点和你当然所站定点在一个方向中,再上一次搜索就标记了,所以拐弯次数不用+1.

 

具体的细节我都写在代码里,还有就是刘汝佳的那本白书里面也有一个一样的迷宫题目,虽然求得结构不一样,但是搜索的方式都是一样的,出了题目的限制有点小改动
大家可以去看看那个理解一下。

代码如下:

 

 

 

C语言: 高亮代码由发芽网提供
01 //逃离迷宫//
02 //题目链接:http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?pid=1006&ojid=0&cid=4532&hide=0//
03 /*
04 #include<stdio.h>
05 #include<iostream>
06 #include<queue>
07 using namespace std;
08 char map[110][110];
09 bool vis[110][110];
10 int sx,sy,ex,ey,n,m,k;
11 int fangxiang[4][2]={-1,0,0,1,1,0,0,-1};
12 struct node
13 {
14     int x,y;
15     int step;
16 }s,e;                                            //s为定点,e为扩展点//
17 queue<node>qu;                  //队列中的一个元素,也就是每个节点包括三个元素,两个位置元素,一个当前走到当前节点的时候的拐弯次数//
18 bool judge(int x,int y)
19 {
20     if(x>=1&&x<=n&&y>=1&&y<=m&&map[x][y]=='.')                            //判断当前的扩展节点是否符合要求,既不能走到迷宫外面,不能走有障碍的地方//
21         return true;
22     else
23         return false;
24 }
25 void BFS()
26 {
27     int i,j;
28     if(sx==ex&&sy==ey)                                        //如果起点就是终点,那么输出然后退出//
29     {
30         printf("yes\n");
31         return;
32     }
33     s.x=sx;s.y=sy;s.step=-1;      //设置第一个定点//
34     vis[sx][sy]=true;           //标记起点//
35     qu.push(s);
36     while(!qu.empty())
37     {
38         s=qu.front();                                            //取起点为定点//
39         qu.pop();                                                 //弹出//
40         for(i=0;i<4;i++)
41         {
42             int tx=s.x+fangxiang[i][0];          //向四个方向走//
43             int ty=s.y+fangxiang[i][1];
44             while(judge(tx,ty))                          //如果这个点满足条件//
45             {
46   //是否已经走过,因为该BFS是一次性把某一个方向都搜完,所以如果已经搜索过,那么再走这一条路的任何一个定点的时候它都不会转弯//
47                 if(vis[tx][ty]==false)                  
48                 {
49                     vis[tx][ty]=true;                                   //标记//
50                     e.x=tx;
51                     e.y=ty;
52                     e.step=s.step+1;
53                     qu.push(e);                                                                 //扩展点入队列//
54                     if(e.x==ex&&e.y==ey&&e.step<=k)              //每加入一个新的定点,就开始判断是不是到了终点//
55                     {
56                         printf("yes\n");
57                         return ;
58                     }
59                 }
60                 tx+=fangxiang[i][0];
61                 ty+=fangxiang[i][1];
62                 //之所以要把定点的四周的所有的定点都如队列,是因为,题目中要求了拐弯数,step初始化为-1,第一个定点为起点之后走的第一个点不算是拐弯数,所以+1等于0 。该题的思路也就是运用BFS的同时,考虑到拐弯数这个条件,把step=0的节点先入队列,因为第一个走的肯定是他们其中的一个,之后再以他们为定点走的扩展点,step一次增加,因为无论向哪个方向走都会拐弯。之后以此类推,把step=1.=2的点都入队列
63             }
64         }
65     }
66         printf("no\n");
67         return ;
68      //能够走到终点的条件一个是起点就是终点另一个就是扩展点就是终点,如果这两个都不是,那么就是走不到终点,可以退出了//
69 }
70 int main()
71 {
72 #ifndef ONLINE_JUDGE
73     freopen("f:\\in.txt","r",stdin);
74 #endif
75     int N;
76     int i;
77     while(scanf("%d",&N)!=EOF)
78     {
79         while(N--)
80         {
81             memset(vis,false,sizeof(vis));
82             memset(map,0,sizeof(map));
83             while(!qu.empty())
84                 qu.pop();                                                     //清空所有数组,为下面的BFS做准备//
85             scanf("%d %d",&n,&m);
86             for(i=1;i<=n;i++)
87                 scanf("%s",map[i]+1);
88             scanf("%d%d%d%d%d",&k,&sy,&sx,&ey,&ex);
89             BFS();
90         }
91     }
92     return 0;
93 }
94 */


 

原创粉丝点击