比较繁琐的一道题目,为了处理上的方便,我们将所有的坐标都扩大三倍,扩大三倍之后,要找出之前的起始点、终止点以及建筑物矩形所围成区域对应的坐标,注意为了建筑物矩形处理的方便,我们将左边右移、右边左移、上边下移、下边上移,然后标注好,同时要注意处理好建筑物的接触点的地方,在进行后面的遍历的时候要注意题目中讲的可以沿着边进行移动,同时要设置对应的数组,记录在每个点的每个方向上是否已经考虑到了,这样可以去重,具体实现见如下代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
#include<functional>
using namespace std;
int dx[] = { -3, 0, 3, 0 };
int dy[] = { 0, 3, 0, -3 };
const int M = 350;
int record_x[M], record_y[M];
int ind_x,ind_y;
int area[M][M];
int Left[M][M], Up[M][M], Right[M][M], Down[M][M], Ban[M][M];
int visit[M][M][4];
class Node{
public:
int x, y, dir, cnt;
Node(int X = 0, int Y = 0, int Dir = -1, int Cnt = 0) :x(X), y(Y), dir(Dir), cnt(Cnt){}
};
class Point{
public:
int l, r, u, d;
};
class Solve{
public:
int startx, starty, endx, endy;
int N;
vector<Point> point;
int search(int aim,bool isx){
if (isx){
for (int i = 1; i <= ind_x; i++){
if (record_x[i] == aim) return i;
}
}
else{
for (int i = 1; i <= ind_y; i++){
if (record_y[i] == aim) return i;
}
}
}
void Init(){
cin >> N;
point.clear();
ind_x = 1, ind_y = 1;
memset(area, 0, sizeof(area));
for (int i = 1; i <= N; i++){
int a, b, c, d;
cin >> a >> b >> c >> d;
Point temp;
temp.l = min(a,c);
temp.r = max(a,c);
temp.d = min(b,d);
temp.u = max(b,d);//保证了u和d的正确性
point.push_back(temp);
record_x[ind_x++] = a, record_x[ind_x++] = c;
record_y[ind_y++] = b, record_y[ind_y++] = d;
}
record_x[ind_x++] = startx, record_x[ind_x++] = endx;
record_y[ind_y++] = starty, record_y[ind_y++] = endy;
ind_x--, ind_y--;
sort(record_x+1,record_x+ind_x+1);
sort(record_y+1,record_y+ind_y+1);
ind_x = unique(record_x+1, record_x + ind_x+1) - (record_x+1);
ind_y = unique(record_y+1, record_y + ind_y+1) - (record_y+1);
startx = search(startx, true) * 3, endx = search(endx, true) * 3;
starty = search(starty, false) * 3, endy = search(endy, false) * 3;
memset(Left, 1, sizeof(Left)), memset(Right, 1, sizeof(Right));
memset(Down, 1, sizeof(Down)), memset(Up, 1, sizeof(Up));
memset(Ban, 0, sizeof(Ban));
for (int i = 0; i < N; i++){
int l = search(point[i].l, true) * 3 + 1;
int r = search(point[i].r, true) * 3 - 1;
int u = search(point[i].u, false) * 3 - 1;
int d = search(point[i].d, false) * 3 + 1;
for (int ind1 = l; ind1 <= r; ind1++){
for (int ind2 = d; ind2 <= u; ind2++){
Ban[ind1][ind2] = 1;
}
}
}
for (int i = 1; i <= ind_x; i++){
for (int j = 1; j <= ind_y; j++){
int newx = i * 3;
int newy = j * 3;
if (Ban[newx][newy] == 1) continue;
if (Ban[newx - 1][newy - 1] && Ban[newx + 1][newy + 1]){
Left[newx][newy] = Right[newx][newy] = Up[newx][newy] = Down[newx][newy] = 1;
}
if (Ban[newx - 1][newy + 1] && Ban[newx + 1][newy - 1]){
Left[newx][newy] = Right[newx][newy] = Up[newx][newy] = Down[newx][newy] = 2;
}
if (Ban[newx - 1][newy + 1] && Ban[newx - 1][newy - 1]) Left[newx][newy] = 0;
if (Ban[newx + 1][newy + 1] && Ban[newx + 1][newy - 1]) Right[newx][newy] = 0;
if (Ban[newx + 1][newy - 1] && Ban[newx - 1][newy - 1]) Down[newx][newy] = 0;
if (Ban[newx + 1][newy + 1] && Ban[newx - 1][newy + 1]) Up[newx][newy] = 0;
}
}
}
int Deal(){
Init();
memset(visit, 0, sizeof(visit));
queue<Node> q;
Node t(startx, starty, -1, 0);
q.push(t);
while (!q.empty()){
Node temp = q.front();
q.pop();
if (temp.x == endx&&temp.y == endy) return temp.cnt;
for (int i = 0; i < 4; i++){
int newx = temp.x, newy = temp.y;
if (i == 0 && !Left[newx][newy] || i == 1 && !Up[newx][newy] ||
i == 2 && !Right[newx][newy] || i == 3 && !Down[newx][newy]) continue;
if (Down[newx][newy] == 1){
if (temp.dir == 0 && (i == 0 || i == 1)) continue;
if (temp.dir == 1 && (i == 1 || i == 0)) continue;
if (temp.dir == 2 && (i == 2 || i == 3)) continue;
if (temp.dir == 3 && (i == 3 || i == 2)) continue;
}
if (Down[newx][newy] == 2){
if (temp.dir == 0 && (i == 0 || i == 3)) continue;
if (temp.dir == 3 && (i == 3 || i == 0)) continue;
if (temp.dir == 1 && (i == 1 || i == 2)) continue;
if (temp.dir == 2 && (i == 2 || i == 1)) continue;
}
newx += dx[i], newy += dy[i];
while (newx >= 1 && newx <= ind_x * 3 && newy >= 1 && newy <= ind_y * 3
&& !Ban[newx][newy]){
Node temp2;
temp2.x = newx, temp2.y = newy;
temp2.dir = i, temp2.cnt = temp.cnt;
if (!visit[temp2.x][temp2.y][temp2.dir]){
visit[temp2.x][temp2.y][temp2.dir] = 1;
if (i != temp.dir&&temp.dir != -1) temp2.cnt++;
q.push(temp2);
}
if (temp2.dir == 0 && !Left[temp2.x][temp2.y] || temp2.dir == 1 && !Up[temp2.x][temp2.y] ||
temp2.dir == 2 && !Right[temp2.x][temp2.y] || temp2.dir == 3 && !Down[temp2.x][temp2.y]) break;
if (Down[temp2.x][temp2.y] == 1 || Down[temp2.x][temp2.y] == 2) break;
newx += dx[i];
newy += dy[i];
}
}
}
return -1;
}
};
int main(){
Solve a;
while (cin >> a.startx >> a.starty >> a.endx >> a.endy){
if (a.startx == 0 && a.starty == 0 && a.endx == 0 && a.endy == 0) break;
cout<<a.Deal()<<endl;
}
return 0;
}