找同學(只能轉彎兩次的"DFS")

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

/*
3 4
4 3 2 1
0 0 0 0
1 2 3 4
4
1 1 2 4
3 4 1 1
2 4 2 1
3 3 1 1
0 0
*/

vector<vector<int>> mp;
bool can1(int m1, int n1, int m2, int n2) {
	// top, down
	int t1 = m1 - 1, d1 = m1 + 1, t2 = m2 - 1, d2 = m2 + 1;
	while (t1 >= 0 && mp[t1][n1] == 0) --t1;
	++t1;
	while (d1 < mp.size() && mp[d1][n1] == 0) ++d1;
	--d1;
	while (t2 >= 0 && mp[t2][n2] == 0) --t2;
	++t2;
	while (d2 < mp.size() && mp[d2][n2] == 0) ++d2;
	--d2;
	const int t = max(t1, t2), d = min(d1, d2);
	if (t <= d) {
		for (int i = t; i <= d; ++i) {
			int left = min(n1, n2), right = max(n1, n2), j;
			if (i == m1) ++left;
			if (i == m2) --right;
			for (j = left; j <= right; ++j)
				if (mp[i][j] != 0)
					break;
			if (j == right + 1)
				return true;
		}
	}
	return false;
}

bool can2(int m1, int n1, int m2, int n2) {
	// left, right
	int l1 = n1 - 1, r1 = n1 + 1, l2 = n2 - 1, r2 = n2 + 1;
	while (l1 >= 0 && mp[m1][l1] == 0) --l1;
	++l1;
	while (r1 < mp.size() && mp[m1][r1] == 0) ++r1;
	--r1;
	while (l2 >= 0 && mp[m2][l2] == 0) --l2;
	++l2;
	while (r2 < mp.size() && mp[m2][r2] == 0) ++r2;
	--r2;
	const int l = max(l1, l2), r = min(r1, r2);
	if (l <= r) {
		for (int j = l; j <= r; ++j) {
			int top = min(m1, m2), down = max(m1, m2), i;
			if (j == n1) ++top;
			if (j == n2) --down;
			for (i = top; i <= down; ++i)
				if (mp[i][j] != 0)
					break;
			if (i == down + 1)
				return true;
		}
	}
	return false;
}

bool canMatch(int m1, int n1, int m2, int n2) {
	//printf("1: mp[%d][%d] = %d, 2: mp[%d][%d] = %d\n", m1, n1, mp[m1][n1], m2, n2, mp[m2][n2]);
	if (mp[m1][n1] == 0 ||
		mp[m2][n2] == 0 ||
		mp[m1][n1] != mp[m2][n2]) return false;
	if (can1(m1, n1, m2, n2)) return true;
	if (can2(m1, n1, m2, n2)) return true;
	return false;
}

int main() {
	while (true) {
		int a, b;
		cin >> a >> b;
		if (a == 0 && b == 0) break;
		mp = vector<vector<int>>(a, vector<int>(b, 0));
		for (int i = 0; i < a; ++i)
			for (int j = 0; j < b; ++j)
				cin >> mp[i][j];
		int k;
		cin >> k;
		for (int i = 0; i < k; ++i) {
			int m1, n1, m2, n2;
			cin >> m1 >> n1 >> m2 >> n2;
			--m1; --n1; --m2; --n2;
			if (canMatch(m1, n1, m2, n2))
				cout << "YES" << endl;
			else
				cout << "NO" << endl;
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章