解析见代码

#define _CRT_SECURE_NO_WARNINGS //这是非一般的最短路,所以广搜到的最短的路不一定是所要的路线 //所以应该把所有的路径都搜索出来,找到最短的转折数,看他是不是不大于2 //我是 用边搜索边更新当前路径的最小转弯数 来写的 #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<queue> using namespace std; #define MAXN 1010 int map[MAXN][MAXN],n,m,turn[MAXN][MAXN]; bool vis[MAXN][MAXN]; int xx[4]={0,0,1,-1}; int yy[4]={1,-1,0,0}; struct tt { int x,y,turn,z;//z表示之前是哪一种方向(0~3),-1是初始位置 }; int bfs(int x1,int y1,int x2,int y2) { tt front,rear,temp; queue<tt>q; while(!q.empty()) q.pop(); memset(vis,false,sizeof(vis)); front.x=x1;front.y=y1;front.turn=0;front.z=-1; q.push(front); vis[x1][y1]=true; while(!q.empty()) { temp=q.front(); if(temp.x==x2&&temp.y==y2) { if(temp.turn<3) return 1; else return 0; } q.pop(); for(int i=0;i<4;i++) { rear.x=temp.x+xx[i]; rear.y=temp.y+yy[i]; rear.z=i; if(temp.z!=-1&&temp.z!=i) rear.turn=temp.turn+1; else rear.turn=temp.turn; if(rear.x==x2&&rear.y==y2) { if(rear.turn<3) return 1; } if(rear.x>=0&&rear.y>=0&&rear.x<n&&rear.y<m&&map[rear.x][rear.y]==0) { if(vis[rear.x][rear.y]==false)//如果没扫描过,就直接加入队列 { q.push(rear); vis[rear.x][rear.y]=true; turn[rear.x][rear.y]=rear.turn;//更新当前点的转弯数 } else//如果之前扫描过了,那就比较一下转弯数,把少的重新更新进队列 { if(rear.turn<turn[rear.x][rear.y]) { q.push(rear); turn[rear.x][rear.y]=rear.turn;//同样更新当前点的转弯数; } } } } } return 0; } int main() { int i,j,x1,x2,y1,y2,t; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0)break; for(i=0;i<n;i++) { for(j=0;j<m;j++) { scanf("%d",&map[i][j]); } } scanf("%d",&t); while(t--) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(map[x1-1][y1-1]!=map[x2-1][y2-1]||map[x1-1][y1-1]==0||map[x2-1][y2-1]==0) printf("NO "); else if(bfs(x1-1,y1-1,x2-1,y2-1)) printf("YES "); else printf("NO "); } } return 0; } /* 8 8 1 2 7 0 0 3 5 6 0 0 4 0 5 6 0 0 0 0 5 0 4 8 7 0 0 0 0 0 0 0 0 0 2 0 8 0 0 0 0 7 6 5 3 0 2 4 0 9 7 0 0 0 0 0 0 7 9 7 9 8 6 6 1 5 100 1 1 8 7 1 2 5 1 3 6 5 3 3 6 8 4 5 8 7 8 */