A monocycle is a cycle that runs on one wheel and the one we will be considering is a bit more special.
It has a solid wheel colored with five different colors as shown in the figure:
The colored segments make equal angles (72o) at the center. A monocyclist rides this cycle on an M × N grid of square tiles. The tiles have such size that moving forward from the center of one tile o that of the next one makes the wheel rotate exactly 72 o around its own center. The effect is shown in the above figure. When the wheel is at the center of square 1, the midpoint of the periphery of its blue segment is in touch with the ground. But when the wheel moves forward to the center of the next
square (square 2) the midpoint of its white segment touches the ground.
Some of the squares of the grid are blocked and hence the cyclist cannot move to them. The cyclist tarts from some square and tries to move to a target square in minimum amount of time. From any square either he moves forward to the next square or he remains in the same square but turns 90o left or right. Each of these actions requires exactly 1 second to execute. He always starts his ride facing
north and with the midpoint of the green segment of his wheel touching the ground. In the target
square, too, the green segment must be touching the ground but he does not care about the direction
he will be facing.
Before he starts his ride, please help him find out whether the destination is reachable and if so the
minimum amount of time he will require to reach it.
Input
The input may contain multiple test cases.
The first line of each test case contains two integers M and N (1 ≤ M, N ≤ 25) giving the
dimensions of the grid. Then follows the description of the grid in M lines of N characters each. The
character ‘#’ will indicate a blocked square, all other squares are free. The starting location of the
cyclist is marked by ‘S’ and the target is marked by ‘T’.
The input terminates with two zeros for M and N.
Output
For each test case in the input first print the test case number on a separate line as shown in the
sample output. If the target location can be reached by the cyclist print the minimum amount of time
(in seconds) required to reach it exactly in the format shown in the sample output, otherwise, print
“destination not reachable”.
Print a blank line between two successive test cases.
Sample Input
1 3
S#T
10 10
#S…#
#…#.##.##
#.##.##.##
.#…##.#
##.##…#.#
#…#.##…
#…##.
…##.##…
#.###…#.
#…###T
0 0
Sample Output
Case #1
destination not reachable
Case #2
minimum time = 49 sec
有个车轮子,车轱辘分成了五部分,每一个部分有个颜色,每走一步,换个颜色; 车还有个方向,每一秒只能往前走,或者转向,就比如现在车面朝右吧,你只能向右走,如果你想往上走,对不起,请先花一秒时间调个头(事事子超多)。地图上还有些障碍物不能走,问,能不能从起点走到终点,还得轮子颜色是最初得颜色,最短时间多少秒。
求从起点到终点得时间,我们很容易想用BFS。
但是这个题又不像普通得走地图一样,它轮子毛病特别多,要求特别多,同一个点,我们有可能走两次(比如我们走到终点了,但是轮子颜色不对,我们得再溜达几步,让轮子颜色便变成合适得),所以每一步得状态要有四部分组成------当前点得坐标x和y,当前轮子得朝向,当前轮子得颜色
int vis[maxx][maxx][4][5];//前两维是坐标 第三维是当前方向,第四维是颜色
struct node { int x; int y; int color;//颜色 int dir;//方向 int time;//用时 friend bool operator < (const node& a,const node& b ) { return a.time>b.time; } };
if(tmp.dir==i)//同方向的 { t.time=tmp.time+1; t.dir=i; t.color=(tmp.color+1)%5; t.x=dx; t.y=dy; }
if(abs(tmp.dir-i)==2)//正好相反方向 t.time=tmp.time+2; else t.time=tmp.time+1;
if(!vis[t.x][t.y][i][t.color])//之前没有过这个状态 { if(t.x==ex&&t.y==ey&&t.color==0)//到终点了 { cout<<"minimum time = "<<t.time<<" sec"<<endl; return ; } q.push(t); vis[t.x][t.y][i][t.color]=1; }
注意开始得时候别忘了把第一个结点加到设计好。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <cmath> using namespace std; const int maxx=100; int n,m; int sx,sy,ex,ey; char mp[maxx][maxx]; int vis[maxx][maxx][4][5];//前两维是坐标 第三维是当前方向,第四维是颜色 struct node { int x; int y; int color;//颜色 int dir;//方向 int time;//用时 friend bool operator < (const node& a,const node& b ) { return a.time>b.time; } }; priority_queue <node >q;//按时间的从小到大的优先队列 保证而每次找到的都是最优的 void bfs(node ss) { struct node tmp,t; int next[4][2] = {{-1,0},{0,1},{1,0},{0,-1}}; while(q.size())//清空队列 q.pop(); q.push(ss); vis[ss.x][ss.y][ss.dir][ss.color]=1; while(!q.empty()) { tmp=q.top(); q.pop(); for(int i=0;i<4;i++)//往周围四个方向走 { int dx=tmp.x+next[i][0]; int dy=tmp.y+next[i][1]; if(dx>=0&&dx<n&&dy>=0&&dy<m&&mp[dx][dy]!='#')//下一个位置是合法的位置 { if(tmp.dir==i)//同方向的 { t.time=tmp.time+1; t.dir=i; t.color=(tmp.color+1)%5; t.x=dx; t.y=dy; } else { if(abs(tmp.dir-i)==2)//正好相反方向 t.time=tmp.time+2; else t.time=tmp.time+1; t.color=tmp.color;//只是转个向但是并不动所以颜色不变 t.dir=i;//转完之后方向就是i了 t.x=tmp.x; t.y=tmp.y; } if(!vis[t.x][t.y][i][t.color])//之前没有过这个状态 { if(t.x==ex&&t.y==ey&&t.color==0)//到终点了 { cout<<"minimum time = "<<t.time<<" sec"<<endl; return ; } q.push(t); vis[t.x][t.y][i][t.color]=1; } } } } cout<<"destination not reachable"<<endl; } void init() { memset(vis,0,sizeof(vis)); } int main() { int cas=1; while(~scanf("%d%d",&n,&m)) { struct node begin; if(n==0&&m==0) break; init(); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { cin>>mp[i][j]; if(mp[i][j]=='S') sx=i,sy=j; else if(mp[i][j]=='T') ex=i,ey=j; } } // cout<<sx<<" "<<sy<<endl; // cout<<ex<<" "<<ey<<endl; begin.x=sx; begin.y=sy; begin.color=0; begin.dir=0; begin.time=0; if(cas!=1) cout<<endl; cout<<"Case #"<<cas++<<endl; bfs(begin); } return 0; }