这道题关键点在于走过的点可能还会重复走(比如去另一个方向获得无敌值再回来),所以用传统的bfs绝对不行,因此需要设一个三维数组vis[a][b][c] 标记点(a,b)在无敌值为c的时候是否已经走过,走过的话就不再走了。只有当去获得无敌值时才会重复走。
#include<bits/stdc++.h>
using namespace std;
int n,k,flag,vis[1005][1005][15]; //vis[a][b][k]表示(a,b)点在无敌值为k的时候是否走过,如果已经走过了那么以后就不会再重复走。再走的话说明是获取到了无敌值
//用这种三维数组标记巧妙的避免了两个点之间的死循环无限走
char mapp[1005][1005];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
struct node{
int x;
int y;
int wd;
int step;
};
void bfs(int x,int y)
{
node p;
queue<node> q;
p.x=x;
p.y=y;
p.wd=0;
p.step=0;
vis[1][1][0]=1;
q.push(p);
while(!q.empty())
{
node u=q.front();
q.pop();
if(u.x==n && u.y==n)
{
flag=1;
cout<<u.step<<endl;
return;
}
for(int i=0;i<4;i++)
{
int tx=u.x+dx[i];
int ty=u.y+dy[i];
if(tx>=1&&tx<=n&&ty>=1&&ty<=n&&mapp[tx][ty]!='#')
{
if(mapp[tx][ty]=='%'&&vis[tx][ty][k]==0) //经过能获得无敌的地方
{
vis[tx][ty][k]=1;
node pp;
pp.x=tx;
pp.y=ty;
pp.step=u.step+1;
pp.wd=k;
q.push(pp);
}
else
{
if(mapp[tx][ty]=='X' && u.wd>0 && vis[tx][ty][u.wd-1]==0)
{
vis[tx][ty][u.wd-1]=1;
node pp;
pp.x=tx;
pp.y=ty;
pp.step=u.step+1;
pp.wd=u.wd-1;
q.push(pp);
}
else if(mapp[tx][ty]=='.' && u.wd>0 && vis[tx][ty][u.wd-1]==0)
{
vis[tx][ty][u.wd-1]=1;
node pp;
pp.x=tx;
pp.y=ty;
pp.step=u.step+1;
pp.wd=u.wd-1;
q.push(pp);
}
else if(mapp[tx][ty]=='.' && u.wd==0 && vis[tx][ty][0]==0)
{
vis[tx][ty][0]=1;
node pp;
pp.x=tx;
pp.y=ty;
pp.step=u.step+1;
pp.wd=0;
q.push(pp);
}
}
}
}
}
}
int main()
{
while(cin>>n>>k)
{
flag=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>mapp[i][j];
}
}
bfs(1,1);
if(flag==0)
cout<<"-1"<<endl;
}
return 0;
}