#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1010;
const int INF = 5;
int n = 0, m = 0, q = 0;
int map[maxn][maxn];
int x1=0, y1=0, x2=0, y2=0;
int dr[4][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
// E W N S
int h = 0, w = 0;
typedef struct node {
int x;
int y;
int dir;//记录走的方向
int tn;//记录转弯次数
}node;
node list[maxn*maxn], E;
int turn[maxn][maxn]; //到达此位置用的最小转弯次数
bool valid(int x, int y) {
if (x<=0 || x>n || y<=0 || y>m) { return false;} //在图中
if (!(0==map[x][y] || (x==x2&&y==y2))) { return false;} //走0或到达终点
return true;
}
int expand(node& R) { //引用
for (int i = 0; i < 4; i++) {
E.x = R.x+dr[i][0];
E.y = R.y+dr[i][1];
E.dir = i;
if (valid(E.x, E.y)) { //剪枝1, 2
if (E.dir != R.dir) {
E.tn = R.tn+1;
}
else {
E.tn = R.tn;
}
if (E.tn<turn[E.x][E.y] && E.tn<3) { //剪枝3, 4转弯次数小于3, 小于已经可达此处的最小转弯次数
if (E.x==x2 && E.y==y2) {
return 1;
}
turn[E.x][E.y] = E.tn; //更新
w++;
list[w] = E;//入队
}
}
}
return 0;
}
bool work() {
for (int i = 0; i<=n; i++) {
for (int j=0; j<=m; j++) {
turn[i][j]=INF;
}
}
if (map[x1][y1] != map[x2][y2]) { return false;}
if (0==map[x1][y1] || 0==map[x2][y2]) { return false;}
//if (!valid(x1, y1) || !valid(x2, y2)) { return false;}
h = 0, w = 0;//队列的两个指针
w++;
list[w].x = x1;
list[w].y = y1;
list[w].tn = -1;
list[w].dir = -1;
turn[x1][y1] = 0;
while (h < w) {
h++;
if (list[h].x==x2 && list[h].y==y2) {
return true;
}
if (expand(list[h])) {
return true;
}
}
return false;
}
int init() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%d", &map[i][j]);
}
}
scanf("%d", &q);
for (int i = 0; i < q; i++) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if (work()) {
printf("YES\n");
}
else {
printf("NO\n");
}
}
return 0;
}
int main()
{
while (2 == scanf("%d%d", &n, &m) && m+n) {
init();
}
return 0;
}