题意解析:其实就是判断起始点能否到达终止点。如果起始点和终止点值不同,直接输出NO。bfs,dfs都行。
附加条件:①不能出边界
②不能走值为0的点
③路径不能转向两次以上
节点需要记录该点的坐标,方向,转向次数。下面是BFS代码(注意剪枝:超过两次的就不要再加入队列了)
#include<iostream>
#include<cstdio>
#include<queue>
#define M 1005
using namespace std;
int G[M][M];
int Hash[M][M]; //记录某条路径在该点转向的次数
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
int n,m;
struct Node
{
int x,y,d,turn;
};
queue<Node>q;
bool bfs(int x1,int y1,int x2,int y2)
{
Node p,t;
while(!q.empty()){
p=q.front();
q.pop();
if(p.x==x2&&p.y==y2&&p.turn<=2) return true; //满足条件
for(int i=0;i<4;i++){
t.x=p.x+dir[i][0];
t.y=p.y+dir[i][1];
if(t.x<1||t.y<1||t.x>n||t.y>m) continue; //出边界情况
if(p.d==i){
t.turn=p.turn;
t.d=p.d;
}
else{
t.turn=p.turn+1;
t.d=i;
}
if(t.turn>2) continue; //转向次数超过两次的(剪枝)
if((!G[t.x][t.y]||(t.x==x2&&t.y==y2))&&Hash[t.x][t.y]>=t.turn){
q.push(t);
Hash[t.x][t.y]=t.turn;
}
}
}
return false;
}
int main()
{
//freopen("d:\\Test.txt","r",stdin);
int x1,x2,y1,y2;
while(scanf("%d%d",&n,&m)&&(n||m)){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&G[i][j]);
}
}
int Q;
scanf("%d",&Q);
for(int i=0;i<Q;i++){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(G[x2][y2]!=G[x1][y1]||G[x1][y1]==0||G[x2][y2]==0||(x1==x2&&y1==y2)){
cout<<"NO"<<endl;
continue;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
Hash[i][j]=11;//初始为较大的数即可
}
}
Hash[x1][y1]=0; //出发点
while(!q.empty()) q.pop();
Node t;
//初始出发点4个方向的值
for(int i=0;i<4;i++){
t.d=i;
t.turn=0;
t.x=x1;
t.y=y1;
q.push(t);
}
if(bfs(x1,y1,x2,y2)) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}