广搜
判断两点能否相连且路径至多有两个转折。
思路:使用二维数组记录到达某点的最小转弯次数(不是最小步数)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstdlib>
#include<map>
#include<set>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define re(x,y) memset(x,y,sizeof(x))
#define rep(x,s,e) for(int x=s;x<e;x++)
#define scan1(x) scanf("%d",&x)
#define scan2(x,y) scanf("%d%d",&x,&y)
#define scan3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define lson i<<1,L,mid
#define rson i<<1|1,mid+1,R
#define M int mid=(L+R)>>1
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxx=1050;
int mx[]= {-1,1,0,0},my[]= {0,0,-1,1};
int mapp[maxx][maxx];
int TU[maxx][maxx];
struct node
{
int x,y;
int i;//记录方向
int turn;
} A,B;
int n,m;
int bfs(int sx,int sy,int ex,int ey)
{
re(TU,inf);
A.x=sx,A.y=sy,A.turn=0;
A.i=-1;
queue<node>q;
q.push(A);
//step[sx][sy]=1;
while(!q.empty())
{
A=q.front();
q.pop();
rep(i,0,4)
{
B.x=A.x+mx[i];
B.y=A.y+my[i];
B.i=i;
if(B.x<1||B.x>n||B.y<1||B.y>m)continue;
if(mapp[B.x][B.y]&&(B.x!=ex||B.y!=ey))continue;
if(!mapp[B.x][B.y])
{
if(A.i==-1)B.turn=A.turn;
else if(A.i==B.i)B.turn=A.turn;
else B.turn=A.turn+1;
if(B.turn>2)continue;
if(TU[B.x][B.y]<B.turn)continue;
TU[B.x][B.y]=B.turn;
q.push(B);
}
else
{
if(A.i==-1)B.turn=A.turn;
else if(A.i==B.i)B.turn=A.turn;
else B.turn=A.turn+1;
if(B.turn>2)continue;
return 1;
}
}
}
return 0;
}
int main()
{
while(~scan2(n,m),n+m)
{
int sx,sy,ex,ey;
int k=1;
rep(i,1,n+1)rep(j,1,m+1)scan1(mapp[i][j]);
int q;
scan1(q);
while(q--)
{
scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
if(mapp[sx][sy]==0||mapp[ex][ey]==0||mapp[sx][sy]!=mapp[ex][ey])
{
printf("NO\n");
continue;
}
if(bfs(sx,sy,ex,ey))printf("YES\n");
else printf("NO\n");
}
}
}
/*
5 4
2 2 0 1
2 0 0 0
1 0 2 0
0 2 2 0
0 0 0 0
1
1 4 3 1
*/