诡异的楼梯
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 19334 Accepted Submission(s): 5048
Problem Description
Hogwarts正式开学以后,Harry发现在Hogwarts里,某些楼梯并不是静止不动的,相反,他们每隔一分钟就变动一次方向.
比如下面的例子里,一开始楼梯在竖直方向,一分钟以后它移动到了水平方向,再过一分钟它又回到了竖直方向.Harry发现对他来说很难找到能使得他最快到达目的地的路线,这时Ron(Harry最好的朋友)告诉Harry正好有一个魔法道具可以帮助他寻找这样的路线,而那个魔法道具上的咒语,正是由你纂写的.
比如下面的例子里,一开始楼梯在竖直方向,一分钟以后它移动到了水平方向,再过一分钟它又回到了竖直方向.Harry发现对他来说很难找到能使得他最快到达目的地的路线,这时Ron(Harry最好的朋友)告诉Harry正好有一个魔法道具可以帮助他寻找这样的路线,而那个魔法道具上的咒语,正是由你纂写的.
Input
测试数据有多组,每组的表述如下:
第一行有两个数,M和N,接下来是一个M行N列的地图,'*'表示障碍物,'.'表示走廊,'|'或者'-'表示一个楼梯,并且标明了它在一开始时所处的位置:'|'表示的楼梯在最开始是竖直方向,'-'表示的楼梯在一开始是水平方向.地图中还有一个'S'是起点,'T'是目标,0<=M,N<=20,地图中不会出现两个相连的梯子.Harry每秒只能停留在'.'或'S'和'T'所标记的格子内.
第一行有两个数,M和N,接下来是一个M行N列的地图,'*'表示障碍物,'.'表示走廊,'|'或者'-'表示一个楼梯,并且标明了它在一开始时所处的位置:'|'表示的楼梯在最开始是竖直方向,'-'表示的楼梯在一开始是水平方向.地图中还有一个'S'是起点,'T'是目标,0<=M,N<=20,地图中不会出现两个相连的梯子.Harry每秒只能停留在'.'或'S'和'T'所标记的格子内.
Output
只有一行,包含一个数T,表示到达目标的最短时间.
注意:Harry只能每次走到相邻的格子而不能斜走,每移动一次恰好为一分钟,并且Harry登上楼梯并经过楼梯到达对面的整个过程只需要一分钟,Harry从来不在楼梯上停留.并且每次楼梯都恰好在Harry移动完毕以后才改变方向.
注意:Harry只能每次走到相邻的格子而不能斜走,每移动一次恰好为一分钟,并且Harry登上楼梯并经过楼梯到达对面的整个过程只需要一分钟,Harry从来不在楼梯上停留.并且每次楼梯都恰好在Harry移动完毕以后才改变方向.
Sample Input
5 5
**..T
**.*.
..|..
.*.*.
S....
Sample Output
7
地图如下:
Hint
Hint这道题和逃出迷宫一样都是使用BFS算法,但是不同的是他要求的是时间,所以有部分修改了,注意。
1 #include<iostream> 2 #include<queue> 3 #include<string.h> 4 using namespace std; 5 6 struct Node{ 7 int x,y,time; 8 }; 9 int M,N;//地图大小 10 char map[25][25]; 11 int vis[25][25]; 12 int xy[4][2]={0,1,0,-1,1,0,-1,0};//方向 13 int start_x,start_y,end_x,end_y;//初始点和结束点 14 queue<Node>que; 15 Node node; 16 17 bool check(int x,int y){//检查当前点能不能走,是不是走过的 18 if(x>=0&&x<M&&y>=0&&y<N&&map[x][y]!='*'&&!vis[x][y]) 19 return true; 20 else return false; 21 } 22 bool check(int x,int y,int z){//检测当遇到楼梯时,楼梯对面能不能走 23 if(z=='N'){ 24 if(y>=0&&y<z&&map[x][y]!='*'&&!vis[x][y]) 25 return true; 26 else return false; 27 } 28 else { 29 if(x>=0&&x<M&&map[x][y]!='*'&&!vis[x][y]) 30 return true; 31 else return false; 32 } 33 } 34 void push_p(int x,int y,int time){//用来保存每个没有走过的点 35 Node temp; 36 temp.x=x;temp.y=y;temp.time=time+1; 37 que.push(temp); 38 return; 39 } 40 41 int BFS(){ 42 int fx,fy;//是下一步将要走到的坐标 43 node.x=start_x; 44 node.y=start_y; 45 node.time=0; 46 que.push(node); 47 while(!que.empty()){ 48 node=que.front(); 49 que.pop(); 50 if(node.x==end_x&&node.y==end_y){//到达终点 51 return node.time; 52 } 53 for(int i=0;i<4;++i){//4个方向走 54 fx=node.x+xy[i][0]; 55 fy=node.y+xy[i][1]; 56 if(check(fx,fy)){//检查下一个点能不能走 57 if(map[fx][fy]=='.'||map[fx][fy]=='T'){//如果不是楼梯,就保存下下一个能走的点 58 push_p(fx,fy,node.time); 59 vis[fx][fy]=1; 60 } 61 else if(map[fx][fy]=='-'){//如果地图上是横着的楼梯 62 if(node.time%2==0){//那么在偶数时间 它是横着的楼梯 63 if(fx==node.x){//看看他是不是横着走过来的 64 if(node.y+1==fy){ 65 fy+=1; 66 } 67 else{ 68 fy-=1; 69 } 70 if(check(fx,fy,N)){//检查楼梯对面 能不能走 71 push_p(fx,fy,node.time); 72 vis[fx][fy]=1; 73 } 74 } 75 else{//如果不是横着走过来的就停下等候楼梯 76 push_p(node.x,node.y,node.time); 77 } 78 } 79 else if(node.time%2!=0){//在奇数时间,它是纵着的楼梯 80 if(fy==node.y){//判断他是不是纵着走过来的 81 if(node.x+1==fx){ 82 fx++; 83 } 84 else{ 85 fx--; 86 } 87 if(check(fx,fy,M)){//判断他能不能到达楼梯对面 88 push_p(fx,fy,node.time); 89 vis[fx][fy]=1; 90 } 91 } 92 else{//如果不是纵着走过来的就停下等候楼梯 93 push_p(node.x,node.y,node.time); 94 } 95 } 96 } 97 else if(map[fx][fy]=='|'){//如果地图上的楼梯是纵着的,意思同上 98 if(node.time%2==0){ 99 if(fy==node.y){ 100 if(node.x+1==fx) fx++; 101 else fx--; 102 if(check(fx,fy,M)){ 103 push_p(fx,fy,node.time); 104 vis[fx][fy]=1; 105 } 106 } 107 else{ 108 push_p(node.x,node.y,node.time); 109 } 110 } 111 else{ 112 if(fx==node.x){ 113 if(node.y+1==fy)fy++; 114 else fy--; 115 if(check(fx,fy,N)){ 116 push_p(fx,fy,node.time); 117 vis[fx][fy]=1; 118 } 119 } 120 else{ 121 push_p(node.x,node.y,node.time); 122 } 123 } 124 } 125 } 126 } 127 } 128 } 129 int main(){ 130 while(cin>>M>>N){ 131 memset(vis,0,sizeof(vis));//初始化用来保存地图上哪个点已经被走过的参数 132 for(int i=0;i<M;i++){//保存下地图 133 for(int j=0;j<N;j++){ 134 cin>>map[i][j]; 135 if(map[i][j]=='S'||map[i][j]=='s'){//标记初始点 136 start_x=i; 137 start_y=j; 138 } 139 if(map[i][j]=='T'||map[i][j]=='t'){//标记结束点 140 end_x=i; 141 end_y=j; 142 } 143 } 144 } 145 vis[start_x][start_y]=1;//初始点被走过 146 while(!que.empty()){//清空队列 147 que.pop(); 148 } 149 int ans=BFS();//获得所走的时间 150 cout<<ans<<endl; 151 } 152 }