半平面交模版
const double eps = 1e-8;
const double PI = acos(-1.0);
int sgn(double x)
{
if (fabs(x) < eps)
{
return 0;
}
if (x < 0)
{
return -1;
}
else
{
return 1;
}
}
struct Point
{
double x, y;
Point(){}
Point(double _x, double _y)
{
x = _x;
y = _y;
}
Point operator - (const Point &b)const
{
return Point(x - b.x, y - b.y);
}
double operator ^ (const Point &b)const
{
return x * b.y - y * b.x;
}
double operator * (const Point &b)const
{
return x * b.x + y * b.y;
}
};
struct Line
{
Point s, e;
double k;
Line() {}
Line(Point _s, Point _e)
{
s = _s;
e = _e;
k = atan2(e.y - s.y, e.x - s.x);
}
Point operator & (const Line &b)const
{
Point res = s;
double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
res.x += (e.x - s.x) * t;
res.y += (e.y - s.y) * t;
return res;
}
};
// 半平面交,直线的左边代表有效区域
bool HPIcmp(Line a, Line b)
{
if (fabs(a.k - b.k) > eps)
{
return a.k < b.k;
}
return ((a.s - b.s) ^ (b.e - b.s)) < 0;
}
Line Q[110];
void HPI(Line line[], int n, Point res[], int &resn)
{
int tot = n;
sort(line, line + n, HPIcmp);
tot = 1;
for (int i = 1; i < n; i++)
{
if (fabs(line[i].k - line[i-1].k) > eps)
{
line[tot++] = line[i];
}
}
int head = 0, tail = 1;
Q[0] = line[0];
Q[1] = line[1];
resn = 0;
for (int i = 2; i < tot; i++)
{
if (fabs((Q[tail].e - Q[tail].s) ^ (Q[tail - 1].e - Q[tail - 1].s)) < eps || fabs((Q[head].e - Q[head].s) ^ (Q[head + 1].e - Q[head + 1].s)) < eps)
{
return;
}
while (head < tail && (((Q[tail] & Q[tail - 1]) - line[i].s) ^ (line[i].e - line[i].s)) > eps)
{
tail--;
}
while (head < tail && (((Q[head] & Q[head + 1]) - line[i].s) ^ (line[i].e - line[i].s)) > eps)
{
head++;
}
Q[++tail] = line[i];
}
while (head < tail && (((Q[tail] & Q[tail - 1]) - Q[head].s) ^ (Q[head].e - Q[head].s)) > eps)
{
tail--;
}
while (head < tail && (((Q[head]&Q[head-1]) - Q[tail].s) ^ (Q[tail].e - Q[tail].e)) > eps)
{
head++;
}
if (tail <= head + 1)
{
return ;
}
for (int i = head; i < tail; i++)
{
res[resn++] = Q[i] & Q[i + 1];
}
if (head < tail - 1)
{
res[resn++] = Q[head]&Q[tail];
}
return ;
}
普通半平面交写法
参考题目链接:
POJ 1750 Dictionary
const double eps = 1e-18;
int sgn(double x)
{
if (fabs(x) < eps)
{
return 0;
}
if (x < 0)
{
return -1;
}
else
{
return 1;
}
}
struct Point
{
double x, y;
Point() {}
Point(double _x, double _y)
{
x = _x;
y = _y;
}
Point operator - (const Point &b)const
{
return Point(x - b.x, y - b.y);
}
double operator ^ (const Point &b)const
{
return x * b.y - y * b.x;
}
double operator * (const Point &b)const
{
return x * b.x + y * b.y;
}
};
// 计算多边形面积
double CalcArea(Point p[], int n)
{
double res = 0;
for (int i = 0; i < n; i++)
{
res += (p[i] ^ p[(i + 1) % n]);
}
return fabs(res / 2);
}
// 通过两点,确定直线方程
void Get_equation(Point p1, Point p2, double &a, double &b, double &c)
{
a = p2.y - p1.y;
b = p1.x - p2.x;
c = p2.x * p1.y - p1.x * p2.y;
return ;
}
// 求交点
Point Intersection(Point p1, Point p2, double a, double b, double c)
{
double u = fabs(a * p1.x + b * p1.y + c);
double v = fabs(a * p2.x + b * p2.y + c);
Point t;
t.x = (p1.x * v + p2.x * u) / (u + v);
t.y = (p1.y * v + p2.y * u) / (u + v);
return t;
}
Point tp[110];
void Cut(double a, double b, double c, Point p[], int &cnt)
{
int tmp = 0;
for (int i = 1; i <= cnt; i++)
{
// 当前点在左侧,逆时针的点
if (a * p[i].x + b * p[i].y + c < eps)
{
tp[++tmp] = p[i];
}
else
{
if (a * p[i - 1].x + b * p[i - 1].y + c < -eps)
{tp[++tmp] = Intersection(p[i - 1], p[i], a, b, c);
}
if (a * p[i + 1].x + b * p[i + 1].y + c < -eps)
{
tp[++tmp] = Intersection(p[i], p[i + 1], a, b, c);
}
}
}
for (int i = 1; i <= tmp; i++)
{
p[i] = tp[i];
}
p[0] = p[tmp];
p[tmp + 1] = p[1];
cnt = tmp;
return ;
}
double V[110], U[110], W[110];
int n;
const double INF = 100000000000.0;
Point p[110];
bool solve(int id)
{
p[1] = Point(0, 0);
p[2] = Point(INF, 0);
p[3] = Point(INF, INF);
p[4] = Point(0, INF);
p[0] = p[4];
p[5] = p[1];
int cnt = 4;
for (int i = 0; i < n; i++)
{
if (i != id)
{
double a = (V[i] - V[id]) / (V[i] * V[id]);
double b = (U[i] - U[id]) / (U[i] * U[id]);
double c = (W[i] - W[id]) / (W[i] * W[id]);
if (sgn(a) == 0 && sgn(b) == 0)
{
if (sgn(c) >= 0)
{
return false;
}
else
{
continue;
}
}
Cut(a, b, c, p, cnt);
}
}
if (sgn(CalcArea(p, cnt)) == 0)
{
return false;
}
else
{
return true;
}
}
int main()
{
while (scanf("%d", &n) == 1)
{
for (int i = 0; i < n; i++)
{
scanf("%lf%lf%lf", &V[i], &U[i], &W[i]);
}
for (int i = 0; i < n; i++)
{
if (solve(i))
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
}
return 0;
}