深搜+剪枝。。。转折次数不能超过两次。。。直接注释到代码里了。。。
#include<stdio.h>
#include<stdlib.h>#include<string.h>
#include<math.h>
#define M 1010
int xs,ys,xe,ye;
int m,n,q,flag;
int a[M][M],f[M][M];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
void dfs(int x,int y,int t,int d)
{
int i,nextx,nexty;
//判断1
if(flag==1) return; //可以消去
if(t>2) return; //不能消去
if(t==2&&x!=xe&&y!=ye) return; //已经转折两次了,可依然不等,故不能消去
//判断2
if(x==xe&&y==ye&&t<=2){ //可以消去
flag=1;
return;
}
for(i=0;i<4;i++){
nextx=x+dir[i][0];
nexty=y+dir[i][1];
if(nextx<1||nextx>m||nexty<1||nexty>n) //出界了
continue;
if(nextx==xe&&nexty==ye) ;
else if(a[nextx][nexty]!=0) //非0,走不通
continue;
if(f[nextx][nexty]!=0) //已走过
continue;
if(d==-1) ;
else if(i!=d) t++; //方向不同,即转折
f[nextx][nexty]=1;
dfs(nextx,nexty,t,i);
f[nextx][nexty]=0;
if(i!=d&&d!=-1)
t--;
//printf("t=%d\n",t);
}
}
int main()
{
int i,j;
while(scanf("%d %d",&m,&n),!(m==0&&n==0)){
memset(f,0,sizeof(f));
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
scanf("%d",&a[i][j]);
scanf("%d",&q);
for(i=0;i<q;i++){
scanf("%d %d %d %d",&xs,&ys,&xe,&ye);
if(xs==xe&&ys==ye){ //起点和终点相同
printf("NO\n");
continue;
}
if(a[xs][ys]!=a[xe][ye]||a[xs][ys]==0||a[xe][ye]==0){ //起点和终点处棋子不等
printf("NO\n");
continue;
}
flag=0;
f[xs][ys]=1;
dfs(xs,ys,0,-1); //从起点处开始深搜
f[xs][ys]=0;
if(flag) printf("YES\n");
else printf("NO\n");
}
}
//system("pause");
return 0;
}