題意解析:其實就是判斷起始點能否到達終止點。如果起始點和終止點值不同,直接輸出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;
}