深搜+剪枝
剪枝:转折点小于等于二、越界、两拼图相同且不重合、选择不能为空
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1005;
int a[MAXN][MAXN], n, m, x_, y_;
//a为拼图,n为行数,m为列数,(x_, y_)为每一次选择的后一个点
int dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 };
bool flag;//标记,判断是否能找到合适的路径
void dfs(int x, int y, int time, int direct) {
if (flag == true || time > 2) return;
if (x == x_ && y == y_) {
flag = true;
return;
}
for (int i = 0; i < 4; i++) {
int nx = x + dir[i][0], ny = y + dir[i][1];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && (a[nx][ny] == 0 || (nx == x_ && ny == y_))) {//判断下一个点在拼图上存在且可行
if(a[nx][ny] == 0) a[nx][ny] = -1;
if (direct != -1 && direct != i)
dfs(nx, ny, time + 1, i);
else
dfs(nx, ny, time, i);
if(a[nx][ny] == -1) a[nx][ny] = 0;
}
}
}
int main() {
int q, x0, y0;
while (cin >> n >> m) {
if (n == 0 && m == 0)
break;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
cin >> a[i][j];
cin >> q;
for (int i = 0; i < q; i++) {
flag = false;
cin >> x0 >> y0 >> x_ >> y_;
x0--;
y0--;
x_--;
y_--;
if (x0 == x_ && y0 == y_) {//不能是两个拼图重合
cout << "NO" << endl;
continue;
}
if (x0 < 0 || x0 >= n || y0 < 0 || y0 >= m || x_ < 0 || x_ >= n || y_ < 0 || y_ >= m) {//判断是否越界
cout << "NO" << endl;
continue;
}
if(a[x0][y0] ==a[x_][y_] && a[x_][y_] != 0)//两个拼图相同且非空
dfs(x0, y0, 0 ,-1);
if (flag == false)
cout << "NO" << endl;
else
cout << "YES" << endl;
}
}
return 0;
}