以为这题和连连看一样水,就很开心的用了dfs然后tle了无数次,好吧,我bfs总行了吧,然后wa了无数次.................
之所以wa是因为在bfs的过程中有些点是可以重复加入队列的.
例如
1
3 3
..*
...
*.*
1 1 1 2 3
这组数据(行,列)
1 (1,1)→(1,2)→(2,2)→(2,3)要转2次弯;
2 (1,1)→(2,1)→(2,2)→(2,3)只转1次弯;所以应该输出yes;
从上面的数据可以看出2次搜索都搜索到了(2,2)这个点,但是2次搜索到改点时的状态却不一样,1中经过该点时转了2次弯,而2种经过该点时却是转了1次弯,因此虽然(2,2)已走过,由于2中的状态要优于1中的状态(转弯次数较小),我们再次搜索到该点时,任要将他加入队列,这和hdu 4528很像.所以我们不能只单纯的标记每个点有没有走过,而是要标记走过该点的状态如何.如果上面的数据能过,那就基本上没问题了.下面为ac代码
#include<iostream>
#include<queue>
#include<cstring>
#define maxn 100+5
using namespace std;
int n,m;
int k,x1,y1,x2,y2;
char mapp[maxn][maxn];
int visit[maxn][maxn];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int flag;
struct stu
{
int x,y,di,lim;
};
void bfs()
{
stu x,y;
queue<stu>root;
x.x=x1;x.y=y1;x.di=-1;x.lim=-1;
root.push(x);
visit[x.x][x.y]=0;
while(root.size())
{
x=root.front() ;
root.pop();
if(x.x==x2&&x.y==y2){flag=1;return;}
for(int i=0;i<4;i++)
{
y.x=x.x+dir[i][0];
y.y=x.y+dir[i][1];
y.di=x.di;
y.lim=x.lim;
if(y.di!=i) y.di=i,y.lim++;
if(y.x<0||y.x>=n||y.y<0||y.y>=m||visit[y.x][y.y]<y.lim||mapp[y.x][y.y]=='*'||y.lim>k) {continue;}
root.push(y);
//cout<<y.x<<y.y<<endl;
visit[y.x][y.y]=y.lim;
}
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>mapp[i];
cin>>k>>y1>>x1>>y2>>x2;
y1--;x1--;y2--;x2--;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
visit[i][j]=1<<20;
}
}
flag=0;
bfs();
if(flag) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
return 0;
}