这个题意是这个的,有一个robot,要从起点走到终点(简化版),它只接受三种命令,
FORWARD X: move forward by X units.
TURN LEFT: turn left (in place) by 90 degrees.
TURN RIGHT: turn right (in place) by 90 degrees.
问:robot从起点走到终点,最短的命令串的长度是多少, 有多少条这样的命令串可以走到终点。
至于FORWARD X: move forward by X units.
也就是说给robot一个向前的命令,它可以走到他前面的任意一个“.”直到遇到“*”或者出了边界。如:
5 6
*....X
.....*
.....*
.....*
N....*
对于图中红色的点, robot从N开始走,只要一个向前的命令就可以走到图中所有的红色点
/*思路 和以前的相比 只要添加一个3维数组记录到每个点的信息即可 即 坐标x y方向dir 三个量记录下来 到每个点所用的最短时间和路数
*/
#include<stdio.h>/*BFS去求最短的路径的条数 是不能标记用没用过的*/
#include<string.h>
#include<limits.h>
#include<queue>
using namespace std;
#define mod 1000000
int hang,lie,e_x,e_y;
char map[105][105];
struct haha
{
int x;
int y;
int time;
int dir; // 不能够用优先队列 要用队列 因为要从某个点向4边扩散记录数组a
// friend bool operator <(struct haha a,struct haha b)
// {
// return a.time>b.time;
// }
}now,next,begin;
struct xixi
{
int num;/*当前最短的次数*/
int time;
}a[105][105][4];
int step[4][2]={-1,0,0,1,1,0,0,-1};
int can(int x,int y)
{
if(x>=0&&x<hang&&y>=0&&y<lie&&map[x][y]=='.')
return 1;
return 0;
}
void BFS()
{
int i,k,xx,yy,ans,ti;
queue<struct haha>que;
que.push(begin);
a[begin.x][begin.y][begin.dir].num=1;/*这里的初始化 千万不要忘记*/
a[begin.x][begin.y][begin.dir].time=0;
while(!que.empty())
{
now=que.front();
que.pop();
if(now.x==e_x&&now.y==e_y) continue;
for(i=0;i<4;i++)
{
xx=now.x+step[i][0];
yy=now.y+step[i][1];
if(!can(xx,yy)) continue; /*看忘各个方向试试能不能走 如果不能走 继续下面的也没有意义了 尤其是转身 都不能走了 你转身干嘛啊*/
if(now.dir==i)/*只有当方向正好与我们要走的方向一样的时候 我们就走*/
{
k=1;/*操 k=1 放进了while里面 一个劲死循环*/
while(1)
{
xx=now.x+step[i][0]*k;
yy=now.y+step[i][1]*k;
if(can(xx,yy))
{
next.dir=i;
next.time=now.time+1;
next.x=xx;
next.y=yy;
if(a[xx][yy][i].time>now.time+1)
{
a[xx][yy][i].time=now.time+1;
a[xx][yy][i].num=a[now.x][now.y][now.dir].num;
a[xx][yy][i].num=a[xx][yy][i].num%mod;/*可以去掉*/
que.push(next);
}
else if(a[xx][yy][i].time==now.time+1)
{
a[xx][yy][i].num+=a[now.x][now.y][now.dir].num;
a[xx][yy][i].num=a[xx][yy][i].num%mod;/*这里就没有必要push了 否则会死循环*/
}
}
else break;
k++;
}
}
else
if(now.dir==(i+2)%4)/*方向和我们要走的方向相反 这时候只转身 等一样了再走*/
{
next.time=now.time+2;
next.dir=i;
next.x=now.x;
next.y=now.y;
if(a[now.x][now.y][i].time>now.time+2)
{/*a[now.x][now.y][now.dir].time+2一开始上面写成这样了不是和当前点的其它方向比 而是找和上一状态到当前状态所用时间的较短的一个*/
a[now.x][now.y][i].time=now.time+2;
a[now.x][now.y][i].num=a[now.x][now.y][now.dir].num;
a[now.x][now.y][i].num=a[now.x][now.y][i].num%mod;
que.push(next);
}
else if(a[now.x][now.y][i].time==now.time+2)
{
a[now.x][now.y][i].num+=a[now.x][now.y][now.dir].num;/*我擦 这里居然让我加了个2 */
a[now.x][now.y][i].num=a[now.x][now.y][i].num%mod;
}
}
else
{
next.time=now.time+1;
next.dir=i;
next.x=now.x;
next.y=now.y;
if(a[now.x][now.y][i].time>now.time+1)
{
a[now.x][now.y][i].time=now.time+1;
a[now.x][now.y][i].num=a[now.x][now.y][now.dir].num;
a[now.x][now.y][i].num=a[now.x][now.y][i].num%mod;
que.push(next);
}
else if(a[now.x][now.y][i].time==now.time+1)
{
a[now.x][now.y][i].num+=a[now.x][now.y][now.dir].num;
a[now.x][now.y][i].num=a[now.x][now.y][i].num%mod;
}
}
}
}
ans=INT_MAX;ti=0;
for(i=0;i<4;i++)
{
if(ans>a[e_x][e_y][i].time)
{
ans=a[e_x][e_y][i].time;
ti=a[e_x][e_y][i].num;
}
else if(ans==a[e_x][e_y][i].time)
{
ti+=a[e_x][e_y][i].num;
ti=ti%mod;
}
}
if(ans==INT_MAX) printf("0 0\n");
else
printf("%d %d\n",ans,ti);
return ;
}
int main()
{
int i,j;
while(scanf("%d %d",&hang,&lie)!=EOF)
{
if(hang+lie==0) break;
for(i=0;i<hang;i++)
for(j=0;j<lie;j++)
for(int k=0;k<4;k++)
{
a[i][j][k].time=INT_MAX;
a[i][j][k].num=0;
}
for(i=0;i<hang;i++)
{
scanf("%s",map[i]);
for(j=0;j<lie;j++)
{
if(map[i][j]=='X') {e_x=i;e_y=j;map[i][j]='.';}
if(map[i][j]=='N') {begin.dir=0;begin.time=0;begin.x=i;begin.y=j;}
else if(map[i][j]=='E') {begin.dir=1;begin.time=0;begin.x=i;begin.y=j;}
else if(map[i][j]=='S') {begin.dir=2;begin.time=0;begin.x=i;begin.y=j;}
else if(map[i][j]=='W') {begin.dir=3;begin.time=0;begin.x=i;begin.y=j;}
}
}
BFS();
}
return 0;
}