标签:
以为这题和连连看一样水,就很开心的用了dfs然后tle了无数次,好吧,我bfs总行了吧,然后wa了无数次.................
之所以wa是因为在bfs的过程中有些点是可以重复加入队列的.
例如
1
3 3
..*
...
*.*
1 1 1 3 2
这组数据(行,列)
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; }
标签:
原文地址:http://blog.csdn.net/zafkiel_nightmare/article/details/45068481