hdu 1180 诡异的楼梯(BFS)

诡异的楼梯

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 8913    Accepted Submission(s): 2205


Problem Description
Hogwarts正式开学以后,Harry发现在Hogwarts里,某些楼梯并不是静止不动的,相反,他们每隔一分钟就变动一次方向. 
比如下面的例子里,一开始楼梯在竖直方向,一分钟以后它移动到了水平方向,再过一分钟它又回到了竖直方向.Harry发现对他来说很难找到能使得他最快到达目的地的路线,这时Ron(Harry最好的朋友)告诉Harry正好有一个魔法道具可以帮助他寻找这样的路线,而那个魔法道具上的咒语,正是由你纂写的. 
 
Input
测试数据有多组,每组的表述如下:
第一行有两个数,M和N,接下来是一个M行N列的地图,'*'表示障碍物,'.'表示走廊,'|'或者'-'表示一个楼梯,并且标明了它在一开始时所处的位置:'|'表示的楼梯在最开始是竖直方向,'-'表示的楼梯在一开始是水平方向.地图中还有一个'S'是起点,'T'是目标,0<=M,N<=20,地图中不会出现两个相连的梯子.Harry每秒只能停留在'.'或'S'和'T'所标记的格子内.
 
Output
只有一行,包含一个数T,表示到达目标的最短时间. 
注意:Harry只能每次走到相邻的格子而不能斜走,每移动一次恰好为一分钟,并且Harry登上楼梯并经过楼梯到达对面的整个过程只需要一分钟,Harry从来不在楼梯上停留.并且每次楼梯都恰好在Harry移动完毕以后才改变方向.
 
Sample Input
5 5 **..T **.*. ..|.. .*.*. S....
 
Sample Output
7
Hint
Hint
地图如下:
 

就是遇到楼梯如果对面的已经访问过,就不用走了,如果对面的没有访问过,如果能直接过,能一下子走2格,如果不能直接过,等楼梯移过来,因为这样时间跟走过去相同,

也不会多。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <string>
  4 #include <cstdio>
  5 #include <queue>
  6 using namespace std;
  7 #define maxn 25
  8 char mp[maxn][maxn];
  9 int vis[maxn][maxn], M, N, sx, sy, tx, ty, ans;
 10 int dir[4][2] = {{0,1}, {0,-1}, {-1,0},{1,0}}; //4个方向 
 11 struct node{
 12     int x, y, t;
 13 };
 14 bool judge(int x, int y){
 15     if(x >= 0 && x < M && y >= 0 && y < N && mp[x][y] != '*' && !vis[x][y]) return 1;
 16     return 0;
 17 }
 18 bool judgeBridge(int x, int y, int t, int dir){ //注意这里要算前一秒的!!!!因为还没走 
 19     if(mp[x][y] == '|') //如果一开始是竖的话 
 20     {
 21         if(t%2==0 && (dir == 2 || dir == 3)) //如果还是竖的,且走的也是竖的 
 22             return 1 ;
 23         else if(t%2 && (dir == 0 || dir == 1)) //如果是横的而且走的也是横的, 
 24             return 1 ;
 25     }
 26     else if(mp[x][y] == '-')  //如果一开始是横的话 
 27     {
 28         if(t%2==0 && (dir == 0 || dir == 1))  //如果还是横的,且走的也是横的 
 29             return 1;
 30         else if(t%2 && (dir == 2 || dir == 3))
 31             return 1;
 32     }
 33     return 0;
 34 } 
 35 node q[maxn*maxn];
 36 int BFS(int sx, int sy){
 37     memset(vis, 0, sizeof(vis));
 38     int front = 0, rear = 1;
 39     q[front].x = sx; q[front].y = sy; q[front].t = 0;
 40     vis[sx][sy] = 1;
 41     while(front < rear){
 42         int x = q[front].x; 
 43         int y = q[front].y;
 44         int t = q[front].t;
 45         front++;
 46         if(x == tx && y == ty) return t;  //如果已经到了终点,跳出
 47         for(int i = 0; i < 4; i++){
 48             int nx = x+dir[i][0];
 49             int ny = y+dir[i][1];
 50             if(judge(nx, ny)){
 51                 if(mp[nx][ny] == '.'){
 52                     vis[nx][ny] = 1;
 53                     node temp;
 54                     temp.x = nx;
 55                     temp.y = ny;
 56                     temp.t = t+1;
 57                     q[rear++] = temp;
 58                 }
 59                 else{
 60                     int nnx = nx + dir[i][0];
 61                     int nny = ny + dir[i][1]; //过桥 
 62                     if(judge(nnx, nny)){ //如果桥对面的点没有访问过的话 
 63                         if(judgeBridge(nx, ny, t,i )){ //过桥 
 64                             vis[nnx][nny] = 1;
 65                             node temp;
 66                             temp.x = nnx;
 67                             temp.y = nny;
 68                             temp.t = t+1;
 69                             q[rear++] = temp;
 70                         }
 71                         else{       //等待 
 72                             node temp;
 73                             temp.x = x;
 74                             temp.y = y;
 75                             temp.t = t+1;
 76                             q[rear++] = temp;
 77                         }
 78                     } 
 79                 }
 80             }
 81         } 
 82          
 83     } 
 84     return -1; 
 85 } 
 86 int main(){
 87     while(~scanf("%d%d", &M, &N)){
 88         for(int i = 0; i < M; i++){
 89             for(int j = 0; j < N; j++){
 90                 cin>>mp[i][j];
 91             }
 92         }
 93         for(int i = 0; i < M; i++){
 94             for(int j = 0; j < N; j++){
 95                 if(mp[i][j] == 'S'){
 96                     mp[i][j] = '.';
 97                     sx = i; sy = j;
 98                 }
 99                 if(mp[i][j] == 'T'){
100                     mp[i][j] ='.';
101                     tx = i; ty = j;
102                 }
103             }
104         }
105         
106         ans = BFS(sx, sy);
107         printf("%d
", ans);
108     }
109     
110     return 0;
111 }

根据这题来个BFS模板吧

 1 int bfs(int sx,int sy) //初始位置 
 2 {
 3     memset(vis, 0 ,sizeof(vis));                            //清空访问数组 
 4     int head = 0,tail=1;                                //头是0, 尾是1, 因为要加入一个数,就是初始位置          
 5     que[head].x=sx ,que[head].y=sy ,que[head].step = 0; //把初始位置加入队列。 
 6     vis[sx][sy] = 1 ;                                   //初始位置标记已经访问过 
 7     while(head < tail)                                  //当队列不为空的时候 
 8     {
 9         int x = que[head].x;
10         int y = que[head].y;
11         int step = que[head].step;  //拿出队首元素 
12         head++ ;                    //弹出 
13         if(x == ex && y == ey)      //如果已经走到终点,退出循环 
14         {
15             return step ;
16         }
17         //如果没有结束 
18         for(int i = 0 ; i < 4 ;i++){  //走上下左右4个方向 
19             int nx = x+d[i][0]
20             int ny = y+d[i][1] ;
21             if(judge(nx, ny)){       //判断满足的条件 ,如果可以走 
22                 if(map[nx][ny] == '.'){ //如果不是楼梯直接入列 
23                     vis[nx][ny] = 1 ;   //标记已经访问过 
24                     que[tail].x = nx ;  
25                     que[tail].y = ny ;
26                     que[tail].step = step+1 ;
27                     tail++;             //加入队列 
28                 }
29                 else//如果是楼梯 
30                 {
31                     int nnx = nx + d[i][0] , nny = ny + d[i][1] ;
32                     //楼梯对面的点没有访问过
33                     if(judge(nnx, nny))
34                     {
35                         if(goStair(nx, ny, step,i))
36                             //判断楼梯此时是否可走
37                         {
38                             //如果可走则直接将该点放入队列,标记为已访问
39                             vis[nnx][nny] = 1;
40                             que[tail].x = nnx ;
41                             que[tail].y = nny;
42                             que[tail].step = step+1 ;
43                             tail++ ;
44                         }
45                         else
46                         {
47                             //如果此时楼梯不能走,则将此时所在的点放回队尾(等待)
48                             que[tail].x = x ;
49                             que[tail].y = y ;
50                             que[tail].step = step+1 ;
51                             tail++ ;
52                         }
53                     }
54                 }
55             }
56         }
57     }
58     return -1 ;
59 }
原文地址:https://www.cnblogs.com/titicia/p/3895996.html