一个让我想死的题目,怎么想都没有想到这个题要用广度优先搜索。而且,题目说了,能左转走,能右转走,不能倒着走。妹的,最后一想,我转2次方向,就面向背面了,相当于“往后转”。而且,“走”,和“转”要分开。
1、输入地图,初始化相关存储变量。
2、广度优先搜索,注意状态记录,“走”,和“转”要分开。
3、输出结果,判断搜索情况,搜索是否成功。
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#define size 27 //最大范围25
using namespace std;
int n,m;
int sx,sy,ex,ey; //起始点,终点坐标
int map[size][size]; //存储地图信息,“-1”不能走,“1”能走
bool flag[size][size][5][4]; //存储搜索状态信息,状态标记【x坐标】【y坐标】【颜色】【方向】
int dir[4][2]={1,0,0,1,-1,0,0,-1}; //四个搜索方向
struct node //节点信息结构体
{
int x; //坐标
int y;
int step;
int time; //耗时
int dict; //方向
int color; //颜色
bool operator <(const node &a)const{ //优先队列,时间小的优先
return time>a.time;
}
}e,s;
void initial() //信息初始化
{
char x[size]; //临时存储地图信息
int i,j;
memset(map,-1,sizeof(map)); //地图信息初始化,不能走
memset(flag,false,sizeof(flag)); //状态标记数组初始化,所有情况都未遍历
for(i=0;i<n;i++) //输入处理地图信息
{
cin>>x;
for(j=0;j<m;j++)
{
if(x[j]=='.')map[i][j]=0; //此处可走
else if(x[j]=='S')sx=i,sy=j,map[i][j]=0; //起始点
else if(x[j]=='T')ex=i,ey=j,map[i][j]=0; //终点
}
}
}
bool inmap(int x,int y) //(x,y)点是否在地图(有效)范围内
{
return x>=0&&x<n&&y>=0&&y<m;
}
int bfs() //广度优先搜索寻路
{
int i,j;
priority_queue<node> q;
s.x=sx; //其实节点初始化
s.y=sy;
s.time=0;
s.step=0;
s.dict=2; //起始方向朝北,根据个人方向数组资料,数据不尽相同
s.color=0; //管它开始什么颜色,方正总共只有5种颜色,最后停下来的时候,还是这个颜色(编号数字相同)就好了
flag[sx][sy][0][2]=true;
q.push(s);
while(!q.empty())
{
s=q.top();
q.pop();
for(i=0;i<4;i++) //四个方向搜索
{
e.x=s.x+dir[i][0];
e.y=s.y+dir[i][1];
e.time=s.time+1;
e.step=s.step+1;
e.dict=i;
e.color=(s.color+1)%5;
if(!inmap(e.x,e.y)||map[e.x][e.y]==-1) continue; //该点不在地图内,该点不可处理
if(e.dict!=s.dict) //方向不同,先转向,不要急着走格子
{
if(e.dict==s.dict+2||e.dict==s.dict-2)e.time++; //反向,要转2次
e.color=s.color;
e.x=s.x; //位置不变,颜色不变
e.y=s.y;
}
if(flag[e.x][e.y][e.color][e.dict]) continue; //这个状态以前走过,不再处理
flag[e.x][e.y][e.color][e.dict]=true; //要处理,标记
if(e.x==ex&&e.y==ey&&e.color==0)return e.time; //走到终点,颜色符合要求,搜索成功
map[e.x][e.y]=e.step;
q.push(e);
}
}
return -1; //搜索失败
}
int main()
{
int j=1;
while(cin>>n>>m&&n+m)
{
initial(); //信息初始化
int ans= bfs(); //广度优先搜索得答案
if(j!=1)cout<<endl; //案例中间有空行
cout<<"Case #"<<j++<<endl;
if(ans==-1)cout<<"destination not reachable"<<endl; //搜索失败
else cout<<"minimum time = "<<ans<<" sec"<<endl; //搜索成功
}
return 0;
}