题意:经典的迷宫问题的基础上,条件是转弯次数的限制,最多k次转弯。
对于这种情况,使用BFS不再是每次添加当前位置周围1步的点,而是将除了走过的以外三个方向上所有的点放入队列。跳入的坑比较多,因为懒,所以没有重新写,总是在之前的上面修修补补。添加点的时候,同一方向上,遇到*停止这个方向的添加,但是遇到添加过的点跳过这个点不添加,但继续向前。
#include<iostream>
#include<queue>
using namespace std;
int m,n;
int map[110][110];
int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
struct local
{
int x;
int y;
int state;
int k;
};
bool bfs(int x1,int y1,int x2,int y2,int k)
{
queue<local>q;
local a;
a.x=x1;
a.y=y1;
a.state=10;
a.k=k;
q.push(a);
map[a.x][a.y]=2;
while(!q.empty())
{
a=q.front();
local t;
// cout<<a.x<<' '<<a.y<<endl;
q.pop();
if(a.x==x2&&a.y==y2) return true;
for(int i=0;i<4;i++)
{
if(a.state-i==2||i-a.state==2) continue;
if(a.x+dir[i][0]<0||a.x+dir[i][0]>=m) continue;
if(a.y+dir[i][1]<0||a.y+dir[i][1]>=n) continue;
if(map[a.x+dir[i][0]][a.y+dir[i][1]]==1) continue;
t.x=a.x+dir[i][0];
t.y=a.y+dir[i][1];
t.k=a.k;
t.state=i;
if(a.state!=i)
{
t.k--;
}
if(t.k<0) continue;
if(map[t.x][t.y]==0) q.push(t);
map[t.x][t.y]=2;
if(t.x+dir[i][0]<0||t.x+dir[i][0]>=m) continue;
if(t.y+dir[i][1]<0||t.y+dir[i][1]>=n) continue;
while(map[t.x+dir[i][0]][t.y+dir[i][1]]!=1)
{
t.x+=dir[i][0];
t.y+=dir[i][1];
if(map[t.x][t.y]==0)q.push(t);
map[t.x][t.y]=2;
if(t.x+dir[i][0]<0||t.x+dir[i][0]>=m) break;
if(t.y+dir[i][1]<0||t.y+dir[i][1]>=n) break;
}
}
}
return false;
}
int main()
{
int tt;
cin>>tt;
while(tt--)
{
cin>>m>>n;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
char ch;
cin>>ch;
if(ch=='.') map[i][j]=0;
else map[i][j]=1;
// cout<<map[i][j];
}
// cout<<endl;
}
int x1,y1,x2,y2,k;
cin>>k>>y1>>x1>>y2>>x2;
if(bfs(x1-1,y1-1,x2-1,y2-1,k+1)) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
}