题目解析:此题的标记数组标记的不是0,1,如果这样的话,走过的点就不能再走了,而对于本题来说,走过的点依然可以再走,vis[]数组记录的是走过这个点的在此次搜索中最小拐弯次数,即使该点走过,如果再一次搜到时拐弯次数小于当前的vis[]数组的值,仍然要把这个点加入队列。同时此题要标记拐弯次数。
代码如下;
#include<stdio.h> #include<string.h> #include<queue> using namespace std; const int INF=0xffffff; //此处注意,因为这个错误,调了半天,注意不要太大 struct node { int x; int y; int d; //标记方向 int s; //标记拐弯次数 }; int m,n; int begin_x,begin_y,end_x,end_y; int map[1006][1006]; int vis[1006][1006]; //此数组标记时,走过的点还可以重复走,只要拐弯次数小于之前走过的点 int dx[6]={0,0,1,-1}; int dy[6]={1,-1,0,0}; bool judge() //用来判断一些不合法是数据 { if(begin_x==end_x&&begin_y==end_y) return false; if(map[begin_x][begin_y]==0||map[end_x][end_y]==0) return false; if(map[begin_x][begin_y]!=map[end_x][end_y]) return false; return true; } void init() //将vis[]数组初始化为无穷大,因为之后要更新vis[]数组,里面存的是更小的值 { for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) vis[i][j]=INF; } void bfs() { init(); node node1,node2; queue<node>q; node1.x=begin_x; node1.y=begin_y; node1.d=-1; //初始没有方向 node1.s=0; //拐弯次数是0 q.push(node1); while(!q.empty()) { node2=q.front(); // printf("%d %d %d %d-->\n",node2.x,node2.y,node2.d,node2.s); q.pop(); if(node2.x==end_x&&node2.y==end_y) { printf("YES\n"); return; } for(int i=0;i<4;i++) { node1.x=node2.x+dx[i]; node1.y=node2.y+dy[i]; node1.d=i; //当前的方向 node1.s=node2.s; //当前节点的拐弯次数等于之前结点的拐弯次数 if(node1.d!=node2.d&&node2.d!=-1) node1.s++; //当前的结点方向跟之前结点方向不相同 if(node1.x<1||node1.x>m||node1.y<1||node1.y>n) continue; //坐标越界 if(node1.s>2) continue; if(map[node1.x][node1.y]&&!(node1.x==end_x&&node1.y==end_y)) continue; //此位置上有数字但不是终点 if(node1.s<vis[node1.x][node1.y]) //如果此点没有访问过那么node1.s肯定小于vis[node1.x][node1.y],如果访问过并且node1.s更小,此时也可以加入队列 { q.push(node1); // printf("***\n"); vis[node1.x][node1.y]=node1.s; } } } printf("NO\n"); } int main() { while(scanf("%d%d",&m,&n)!=EOF&&(m+n)) { for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) scanf("%d",&map[i][j]); int q; scanf("%d",&q); while(q--) { scanf("%d%d%d%d",&begin_x,&begin_y,&end_x,&end_y); if(judge()) bfs(); else printf("NO\n"); } } return 0; }