给出一些直线,问从正上方往下看能看到哪些直线。
一道简单的计算几何题,不过我决定硬搞成半平面交233
稍微改了下,因为是维护上凸壳,所以不用处理首尾半平面相交的问题了。
y=ax+b的直线过定点(0,b),方向向量(1,a)。
right函数改成<=了。否则样例会错。
忘记排序编号怒WA一发233.
判断double没有判精度直接用==并没有WA,好神奇。之前也一直没有判精度。
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 50001;
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); }
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; }
Point operator *(double b) const { return Point(b * x, b * y); }
bool operator ==(const Point &b) const { return x == b.x && y == b.y; }
} p[N];
struct Line {
Point x, v;
double ang; int id;
Line(){}
Line(const Point &_x, const Point &_v) : x(_x), v(_v) {
ang = atan2(v.y, v.x);
}
bool operator <(const Line &b) const {
if (ang == b.ang) return v * (b.x - x) < 0;
return ang < b.ang;
}
bool operator ==(const Line &b) const { return ang == b.ang; }
Point intersection(const Line &b) {
Point u = x - b.x;
double t = (b.v * u) / (v * b.v);
return x + v * t;
}
} l[N], q[N];
bool right(const Point &p, const Line &l) {
return l.v * (p - l.x) <= 0;
}
int main() {
static int ans[N];
int n, i, f = 1, r = 0, m = 0;
double a, b;
scanf("%d", &n);
for (i = 1; i <= n; i++) {
scanf("%lf%lf", &a, &b);
l[i] = Line(Point(0, b), Point(1, a));
l[i].id = i;
}
sort(l + 1, l + n + 1);
n = unique(l + 1, l + n + 1) - (l + 1);
q[++r] = l[1]; q[++r] = l[2];
for (i = 3; i <= n; i++) {
while (f < r && right(q[r].intersection(q[r - 1]), l[i])) r--;
while (f < r && right(q[f].intersection(q[f + 1]), l[i])) f++;
q[++r] = l[i];
}
for (i = f; i <= r; i++)
ans[++m] = q[i].id;
sort(ans + 1, ans + m + 1);
for (i = 1; i <= m; i++)
printf("%d ", ans[i]);
return 0;
}
1007: [HNOI2008]水平可见直线
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5073 Solved: 1876
[ Submit][ Status][ Discuss]
Description
在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的.
例如,对于直线:
L1:y=x; L2:y=-x; L3:y=0
则L1和L2是可见的,L3是被覆盖的.
给出n条直线,表示成y=Ax+B的形式(|A|,|B|<=500000),且n条直线两两不重合.求出所有可见的直线.
Input
第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi
Output
从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格
Sample Input
3
-1 0
1 0
0 0
-1 0
1 0
0 0
Sample Output
1 2