题目:click here ~
题意:
二维平面内给n个矩形,再给2个点,求两点之间所有路径中最少的拐弯次数。
思路:
离散化矩形,因为矩形边界可以走,所以还是有点麻烦的,将一个1*1的方格看做3*3的方格后就好处理了。最重要的问题就是该怎样表示矩形。
#pragma warning(disable:4996)
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
using namespace std;
const int N = 450;
const int M = 10000010;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double PI = acos(-1.0);
int g[N][N];
int step[N][N];
int opx[] = { 1, -1, 0, 0 };
int opy[] = { 0, 0, 1, -1 };
int si, sj, ei, ej;
int xy_size;
struct Rect
{
int x1, y1, x2, y2;
}rect[N];
struct Edge
{
int x, y, turn;
}ss, now, x_head[M];
int X[N], Y[N];
int nx, ny;
int n;
int get_x(int x)
{
int l, r, mid;
l = 1; r = nx;
while (l <= r)
{
mid = (l + r) >> 1;
if (X[mid] == x)
return mid;
else
if (X[mid] > x)
r = mid - 1;
else
l = mid + 1;
}
return mid;
}
int get_y(int x)
{
int l, r, mid;
l = 1; r = ny;
while (l <= r)
{
mid = (l + r) >> 1;
if (Y[mid] == x)
return mid;
else
if (Y[mid] > x)
r = mid - 1;
else
l = mid + 1;
}
return mid;
}
void add(int l1, int r1, int l2, int r2)
{
int i;
for (i = l2; i <= r2; i++)
{
g[l1][i] = g[r1][i] = 1;
if (g[l1 - 2][i] == 1)
g[l1 - 1][i] = 1;
if (g[r1 - 2][i] == 1)
g[r1 + 1][i] = 1;
}
for (i = l1 + 1; i < r1; i++)
{
g[i][l2] = g[i][r2] = 1;
if (g[i][l2 - 2] == 1)
g[i][l2 - 1] = 1;
if (g[i][r2 + 2] == 1)
g[i][r2 + 1] = 1;
}
if (g[r1 + 2][r2 + 2] == 1)
g[r1 + 1][r2 + 1] = 1;
if (g[l1 - 2][l2 - 2] == 1)
g[l1 - 1][l2 - 1] = 1;
if (g[l1 - 2][r2 + 2] == 1)
g[l1 - 1][r2 + 1] = 1;
if (g[r1 + 2][l2 - 2] == 1)
g[r1 + 1][l2 - 1] = 1;
}
void make_edge()
{
int i, j;
memset(g, 0, sizeof(g));
int l1, r1, l2, r2;
si = get_x(rect[0].x1);
sj = get_y(rect[0].y1);
ei = get_x(rect[0].x2);
ej = get_y(rect[0].y2);
for (i = ei * 3; i >= ei * 3 - 2; i--)
{
for (j = ej * 3; j >= ej * 3 - 2; j--)
g[i][j] = 5;
}
for (i = 1; i <= n; i++)
{
l1 = get_x(rect[i].x1);
r1 = get_x(rect[i].x2);
l2 = get_y(rect[i].y1);
r2 = get_y(rect[i].y2);
add(l1 * 3, r1 * 3 - 2, l2 * 3, r2 * 3 - 2);
}
}
bool judge(int x, int y)
{
return (x >= 0 && y >= 0 && x <= nx + nx + nx + 1 && y <= ny + ny + ny + 1);
}
void bfs()
{
int head, tail;
int i, j;
head = tail = 0;
ss.turn = -1;
for (i = si * 3; i >= si * 3 - 2; i--)
{
for (j = sj * 3; j >= sj * 3 - 2; j--)
if (g[i][j] != 1)
{
ss.x = i;
ss.y = j;
x_head[tail++] = ss;
}
}
while (head != tail)
{
now = x_head[head++];
if (head >= M)
head -= M;
for (i = 0; i < 4; i++)
{
ss = now;
ss.turn++;
int tx = ss.x + opx[i];
int ty = ss.y + opy[i];
while (judge(tx, ty) && g[tx][ty] != 1)
{
if (step[tx][ty] > ss.turn)
{
step[tx][ty] = ss.turn;
ss.x = tx;
ss.y = ty;
if (g[tx][ty] == 5)
{
printf("%d\n", step[tx][ty]);
return;
}
x_head[tail++] = ss;
if (tail >= M)
tail -= M;
}
tx += opx[i];
ty += opy[i];
}
}
}
printf("-1\n");
}
void solve()
{
int i, j;
for (i = 0; i <= 3 * nx + 1; i++)
{
for (j = 0; j <= 3 * ny + 1; j++)
step[i][j] = INF;
}
bfs();
}
bool read()
{
int i, j;
scanf("%d%d%d%d", &X[1], &Y[1], &X[2], &Y[2]);
rect[0].x1 = X[1];
rect[0].y1 = Y[1];
rect[0].x2 = X[2];
rect[0].y2 = Y[2];
if (!X[1] && !Y[1] && !X[2] && !Y[2])
return false;
scanf("%d", &n);
j = 3;
for (i = 1; i <= n; i++)
{
scanf("%d%d%d%d", &rect[i].x1, &rect[i].y1, &rect[i].x2, &rect[i].y2);
X[j] = rect[i].x1;
Y[j++] = rect[i].y1;
X[j] = rect[i].x2;
Y[j++] = rect[i].y2;
}
xy_size = j;
sort(X + 1, X + xy_size);
sort(Y + 1, Y + xy_size);
return true;
}
void computing()
{
int i;
nx = 2;
for (i = 2; i < xy_size; i++)
if (X[i] != X[i - 1])
X[nx++] = X[i];
nx--;
ny = 2;
for (i = 2; i < xy_size; i++)
if (Y[i] != Y[i - 1])
Y[ny++] = Y[i];
ny--;
make_edge();
solve();
}
int main()
{
while (read())
{
computing();
}
return 0;
}