题目意思:hdu1180,给你一张图,图上有些障碍物和楼梯,每走一步楼梯的状态会改变。问从起点到终点至少要多少步。
解题思路:标准bfs题目,每次要走新的一步时,判断如下:
1.如果新的位置不在图内,或在图内但是*时或已经访问过时,则不处理;
2.如果新位置是.时,移动到新位置步数加1入队列;
3.左右移动时如果楼梯刚好是’-‘则可越过;上下移动,如果楼梯刚好是’|'也刚好可越过。都移动到新位置则步数加1队列;
4.否则原地等待楼梯转到正确方向。
1.初始化时T必须改为. 否则搜索不到; 2.设置一个变量pStep记录上一个节点的步数,如果当前队列front节点的步数step与pStep不相等,则要改变楼梯的状态。
代码明细:
//probID: hdu1180
//author: WiselyQY
//date: 2021-01-03
#include <bits/stdc++.h>
using namespace std;
const int INF=1<<30;
//用于记录目前的位置和已用的时间
struct Node
{
int x,y,step;
};
int m,n,vis[25][25],sx,sy,ex,ey,ans; //(sx,sy)为起点坐标,(ex,ey)为终点坐标
char g[25][25];
queue<Node> q;
const int dx[]={1,0,-1,0}, dy[]={0,1,0,-1}; //DRUL四个方向
void changeState() //改变楼梯的状态
{
for(int i=0; i<m; i++)
for(int j=0; j<n; j++)
if(g[i][j]=='-') g[i][j]='|';
else if (g[i][j]=='|') g[i][j]='-';
}
int in(int x, int y)
{
return x>=0 && x<m && y>=0 && y<n;
}
void bfs()
{
Node u;
u.x=sx; u.y=sy; u.step=0;
memset(vis,0,sizeof(vis));
vis[u.x][u.y]=1;
while(!q.empty()) q.pop();
q.push(u);
int pStep=0; //用于记录上一个从q队列pop出来的结点的步数
while(!q.empty())
{
u=q.front(); q.pop();
int x=u.x, y=u.y, step=u.step;
if(x==ex && y==ey) {ans=step; return;}//找到结果,返回
if(pStep!=step) {pStep=step; changeState();} //如果当前步数和上一个节点的步数不同,则证明步数已增加1,必须改变楼梯的状态
for(int i=0; i<4; i++)
{
int nx=x+dx[i], ny=y+dy[i];
if(!in(nx,ny) || g[nx][ny]=='*' || vis[nx][ny]) continue; //不在范围内,或在范围内但不可行或已经访问过,则不用处理
Node nu;
if(g[nx][ny]=='.') //移动到新位置
{
vis[nx][ny]=1;
nu.x=nx; nu.y=ny; nu.step=step+1;
q.push(nu);
}
//i为1和3时是左右移动,如果楼梯刚好是'-'则可越过;i为0和2时是上下移动,如果楼梯刚好是'|'也刚好可越过
else if((g[nx][ny]=='-' && i%2) || (g[nx][ny]=='|' && !(i%2)))
{
nx+=dx[i]; ny+=dy[i];
if(!in(nx,ny) || g[nx][ny]=='*' || vis[nx][ny]) continue;
vis[nx][ny]=1;
nu.x=nx; nu.y=ny; nu.step=step+1;
q.push(nu);
}
else //楼梯位置与当前方向刚好相反,原地等待一步
{
nu=u;
nu.step+=1;
q.push(nu);
}
}
}
}
int main()
{
clock_t start,end;
start=clock();
#ifndef ONLINE_JUDGE
freopen(R"(D:\code\hdu\1180\in.txt)","r",stdin);
#endif
while(cin>>m>>n)
{
for(int i=0; i<m; i++)
for(int j=0; j<n; j++)
{
cin>>g[i][j];
if(g[i][j]=='S') {sx=i; sy=j; g[i][j]='.';}
if(g[i][j]=='T') {ex=i; ey=j; g[i][j]='.';}//必须把重点从T改为. 不然搜索不到
}
ans=INF;
bfs();
cout<<ans<<endl;
}
end=clock();
//printf("time=%lfs\n",(double)(end-start)/1000);
return 0;
}