Problem D
独轮车
时限:1000ms 内存限制:10000K 总时限:3000ms
描述:
独轮车的轮子上有红、黄、蓝、白、绿(依顺时针序)5种颜色,在一个如下图所示的20*20的迷宫内每走一个格子,轮子上的颜色变化一次。独轮车只能向前推或在原地转向。每走一格或原地转向90度均消耗一个单位时间。现给定一个起点(S)和一个终点(T),求独轮车以轮子上的指定颜色到达终点所需的最短时间。
输入:
本题包含一个测例。测例中分别用一个大写字母表示方向和轮子的颜色,其对应关系为:E-东、S-南、W-西、N-北;R-红、Y-黄、B-蓝、W-白、G-绿。在测试数据的第一行有以空格分隔的两个整数和两个大写字母,分别表示起点的坐标S(x,y)、轮子的颜色和开始的方向,第二行有以空格分隔的两个整数和一个大写字母,表示终点的坐标T(x,y)和到达终点时轮子的颜色,从第三行开始的20行每行内包含20个字符,表示迷宫的状态。其中'X'表示建筑物,'.'表示路.
输出:
在单独的一行内输出一个整数,即满足题目要求的最短时间。
输入样例:
3 4 R N
15 17 Y
XXXXXXXXXXXXXXXXXXXX
X.X...XXXXXX......XX
X.X.X.....X..XXXX..X
X.XXXXXXX.XXXXXXXX.X
X.X.XX....X........X
X...XXXXX.X.XX.X.XXX
X.X.XX....X.X..X.X.X
X.X.X..XX...XXXX.XXX
X.X.XX.XX.X....X.X.X
X.X....XX.X.XX.X.X.X
X.X.X.XXXXX.XX.X.XXX
X.X.X.XXXXX....X...X
X.X.......X.XX...X.X
X.XXX.XXX.X.XXXXXXXX
X.....XX.......X...X
XXXXX....X.XXXXXXX.X
X..XXXXXXX.XXX.XXX.X
X.XX...........X...X
X..X.XXXX.XXXX...XXX
XXXXXXXXXXXXXXXXXXXX
输出样例:
56
来源:
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define MAXN 210
char mapp[MAXN][MAXN];
int visit[MAXN][MAXN][6][6];
int dirx[4]={-1,1,0,0}; //上,下,左,右
int diry[4]={0,0,-1,1};
struct Node
{
int x,y,color,dir,step;
};
queue<Node> q;
Node s,e;
int check(struct Node X)
{
if(X.x<=0||X.x>20||X.y<=0||X.y>20||mapp[X.x][X.y]=='X'||visit[X.x][X.y][X.color][X.dir]==1)
return 0;
return 1;
}
int bfs()
{
Node a,b;
a.x=s.x,a.y=s.y,a.color=s.color,a.dir=s.dir,a.step=0;
q.push(a);
while(!q.empty())
{
a=q.front();
q.pop();
if(a.x==e.x&&a.y==e.y&&a.color==e.color) return a.step; //return 是在pop的时候就return
if(a.dir==0)
{
b=a; b.color=(a.color+1)%5;
b.x=a.x-1;b.y=a.y;b.dir=a.dir; //step可以是step+1,也可是step+2 ,统称为下一步伐,在一些情况下,step+2可能通过广搜
if(check(b)) //难找最短,要么优先队列,要么将问题转为step+1的情况
{
visit[b.x][b.y][b.color][b.dir]=1;
b.step=a.step+1;
q.push(b);
}
}
else if(a.dir==1)
{
b=a; b.color=(a.color+1)%5;
b.x=a.x;b.y=a.y-1;b.dir=a.dir;
if(check(b))
{
visit[b.x][b.y][b.color][b.dir]=1;
b.step=a.step+1;
q.push(b);
}
}
else if(a.dir==2)
{
b=a; b.color=(a.color+1)%5;
b.x=a.x+1; b.y=a.y; b.dir=a.dir;
if(check(b))
{
visit[b.x][b.y][b.color][b.dir]=1;
b.step=a.step+1;
q.push(b);
}
}
else if(a.dir==3)
{
b=a; b.color=(a.color+1)%5;
b.x=a.x; b.y=a.y+1; b.dir=a.dir;
if(check(b))
{
visit[b.x][b.y][b.color][b.dir]=1;
b.step=a.step+1;
q.push(b);
}
}
b=a; b.dir=(a.dir+1)%4; if(check(b)) {visit[b.x][b.y][b.color][b.dir]=1; b.step=a.step+1; q.push(b);} //原地转动不变色
b=a; b.dir=(a.dir-1+4)%4; if(check(b)) {visit[b.x][b.y][b.color][b.dir]=1; b.step=a.step+1; q.push(b);}
}
return -1; //找不到输出-1;
}
int main()
{
int i,j;
char a,b,c;
scanf("%d %d %c %c",&s.x,&s.y,&a,&b);
scanf("%d %d %c",&e.x,&e.y,&c);
switch(a)
{
case 'R':s.color=0;break;
case 'Y':s.color=1;break;
case 'B':s.color=2;break;
case 'W':s.color=3;break;
case 'G':s.color=4;break;
}
switch(b)
{
case 'N':s.dir=0;break;
case 'W':s.dir=1;break;
case 'S':s.dir=2;break;
case 'E':s.dir=3;break;
}
switch(c)
{
case 'R':e.color=0;break;
case 'Y':e.color=1;break;
case 'B':e.color=2;break;
case 'W':e.color=3;break;
case 'G':e.color=4;break;
}
for(i=1;i<=20;i++)
{
getchar();
for(j=1;j<=20;j++)
scanf("%c",&mapp[i][j]);
}
memset(visit,0,sizeof(visit));
visit[s.x][s.y][s.color][s.dir]=1;
int ans=bfs();
printf("%d\n",ans);
return 0;
}