poj1066

题意:给出图中所有线段,和一个点,问这个点要出正方形至少穿越多少线。

分析:所有线段端点都在正方形周边线上。走弯路是无意义的,不会使穿过的墙减少,因为线段都是接边界的,无法绕过。我们枚举周边线上的出口,连直线,看最少有几个交点。因为只有跨越端点的时候才会改变交点数量。所以我们只需在每两个端点间枚举一个点。

View Code
#include <iostream>
#include
<cstdlib>
#include
<cstring>
#include
<cstdio>
#include
<algorithm>
#include
<cmath>
using namespace std;

#define maxn 50
#define zero(x) (((x)>0?(x):-(x))<eps)
#define eps 1.0E-8

struct Point
{
double x, y;
Point()
{
}
Point(
double xx, double yy) :
x(xx), y(yy)
{
}
} point[maxn
* 2], s;

struct Line
{
Point a, b;
Line()
{
}
Line(Point aa, Point bb) :
a(aa), b(bb)
{
}
} line[maxn];

int n, m, ans;

bool operator <(const Point &a, const Point &b)
{
return atan2(a.y, a.x) < atan2(b.y, b.x);
}

double xmult(Point p1, Point p2, Point p0)
{
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}

int same_side(Point p1, Point p2, Line l)
{
return xmult(l.a, p1, l.b) * xmult(l.a, p2, l.b) > eps;
}

int dots_inline(Point p1, Line l)
{
return zero(xmult(p1, l.a, l.b));
}

int dot_online_in(Point p, Line l)
{
return zero(xmult(p, l.a, l.b)) && (l.a.x - p.x) * (l.b.x - p.x) < eps && (l.a.y - p.y) * (l.b.y - p.y) < eps;
}

int intersect_in(Line u, Line v)
{
if (!dots_inline(v.a, u) || !dots_inline(v.b, u))
return !same_side(u.a, u.b, v) && !same_side(v.a, v.b, u);
return dot_online_in(u.a, v) || dot_online_in(u.b, v) || dot_online_in(v.a, u) || dot_online_in(v.b, u);
}

int opposite_side(Point p1, Point p2, Line l)
{
return xmult(l.a, p1, l.b) * xmult(l.a, p2, l.b) < -eps;
}

int intersect_ex(Line u, Line v)
{
return opposite_side(u.a, u.b, v) && opposite_side(v.a, v.b, u);
}

void input()
{
scanf(
"%d", &m);
n
= 0;
for (int i = 0; i < m; i++)
{
scanf(
"%lf%lf", &point[n].x, &point[n].y);
point[n].x
-= 50;
point[n].y
-= 50;
n
++;
scanf(
"%lf%lf", &point[n].x, &point[n].y);
point[n].x
-= 50;
point[n].y
-= 50;
n
++;
line[i]
= Line(point[i * 2], point[i * 2 + 1]);
}
point[n].x
= -50;
point[n
++].y = -50;
point[n].x
= 50;
point[n
++].y = 50;
point[n].x
= 50;
point[n
++].y = -50;
point[n].x
= -50;
point[n
++].y = 50;
scanf(
"%lf%lf", &s.x, &s.y);
s.x
-= 50;
s.y
-= 50;
}

Point mid_point(Point
&a, Point &b)
{
return Point((a.x + b.x) / 2, (a.y + b.y) / 2);
}

void work()
{
point[n]
= point[0];
ans
= m;
for (int i = 0; i < n; i++)
{
Line l(s, mid_point(point[i], point[i
+ 1]));
int temp = 0;
for (int i = 0; i < m; i++)
if (intersect_in(l, line[i]))
temp
++;
ans
= min(ans, temp);
}
}

int main()
{
//freopen("t.txt", "r", stdin);
input();
sort(point, point
+ n);
// for (int i = 0; i < n; i++)
// printf("%f %f\n", point[i].x, point[i].y);
work();
printf(
"Number of doors = %d\n", ans + 1);
return 0;
}
原文地址:https://www.cnblogs.com/rainydays/p/2181250.html