线段相交水题,维护一个队列就行。。。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cmath> #include <time.h> #define maxn 1000005 #define maxm 2000005 #define eps 1e-10 #define mod 1000000007 #define INF 1e9 #define lowbit(x) (x&(-x)) #define mp make_pair #define ls o<<1 #define rs o<<1 | 1 #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R typedef long long LL; typedef unsigned long long ULL; //typedef int LL; using namespace std; int dcmp(double d) { if(fabs(d) < eps) return 0; else return d > eps ? 1 : -1; } struct point { double x, y; point(double x = 0, double y = 0) : x(x), y(y) {} bool operator < (const point& b) const { if(dcmp(x - b.x) == 0) return dcmp(y - b.y) < 0; else return x < b.x; } bool operator == (const point& b) const { return dcmp(x - b.x) == 0 && dcmp(y - b.y) == 0; } 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); } point operator * (double b) const { return point(x * b, y * b); } point operator / (double b) const { return point(x / b, y / b); } void out(void) { printf("x = %.3f y = %.3f\n", x, y); } }; typedef point vec; //点积 double dot(vec a, vec b) { return a.x * b.x + a.y * b.y; } //向量的长度 double length(vec a) { return sqrt(dot(a, a)); } //两个向量的夹角 double angle(vec a, vec b) { return acos(dot(a, b) / length(a) / length(b)); } //向量叉积 double cross(vec a, vec b) { return a.x * b.y - a.y * b.x; } //向量旋转,rad是弧度 vec rotate(vec a, double rad) { return vec(a.x * cos(rad) - a.y * sin(rad), a.x * sin(rad) + a.y * cos(rad)); } //求法向量,顺时针旋转90度 vec normal(vec a) { double L = length(a); return vec(-a.y / L, a.x / L); } //求两条直线的交点,调用前要确保两条直线相交 point intersection(point a, vec v1, point b, vec v2) { vec u = a - b; double t = cross(v2, u) / cross(v1, v2); return a + v1 * t; } //求点到直线的距离 double distoline(point p, point a, point b) { vec v1 = b - a, v2 = p - a; return fabs(cross(v1, v2)) / length(v1); //如果不取绝对值得到的是有向距离 } //求点到线段的距离 double distosegment(point p, point a, point b) { if(a == b) return length(p - a); vec v1 = b - a, v2 = p - a, v3 = p - b; if(dcmp(dot(v1, v2)) < 0) return length(v2); else if(dcmp(dot(v1, v3)) > 0) return length(v3); else return fabs(cross(v1, v2)) / length(v1); } //点在线段上的投影 point projection(point p, point a, point b) { vec v = b - a; return a + v * (dot(v, p - a) / dot(v, v)); } //已经知道p在ab直线上,判断p和线段ab的关系 //p在不在线段上返回1,在线段端点返回0,在线段上返回-1 int onseg(point p, point a, point b) { if(fabs(a.x - b.x) > fabs(a.y - b.y)) return dcmp(p.x - a.x) * dcmp(p.x - b.x); else return dcmp(p.y - a.y) * dcmp(p.y - b.y); } //线段相交,规范相交返回1,不规范相交返回2,不相交返回0 bool segtoseg(point a1, point b1, point a2, point b2) { int d1 = dcmp(cross(b1 - a1, a2 - a1)); int d2 = dcmp(cross(b1 - a1, b2 - a1)); int d3 = dcmp(cross(b2 - a2, a1 - a2)); int d4 = dcmp(cross(b2 - a2, b1 - a2)); if(d1 * d2 < 0 && d3 * d4 < 0) return 1; if(d1 == 0 && onseg(a2, a1, b1) <= 0) return 2; if(d2 == 0 && onseg(b2, a1, b1) <= 0) return 2; if(d3 == 0 && onseg(a1, a2, b2) <= 0) return 2; if(d4 == 0 && onseg(b1, a2, b2) <= 0) return 2; return 0; } struct segment { point a, b; }s[maxn]; int q[2][1005]; int n; void work(void) { int now = 0, cnt = 0, next; for(int i = 1; i <= n; i++) { scanf("%lf%lf%lf%lf", &s[i].a.x, &s[i].a.y, &s[i].b.x, &s[i].b.y); next = now ^ 1; int t = 0; for(int j = 1; j <= cnt; j++) if(segtoseg(s[q[now][j]].a, s[q[now][j]].b, s[i].a, s[i].b) == 0) q[next][++t] = q[now][j]; q[next][++t] = i; now = next, cnt = t; } printf("Top sticks: "); for(int i = 1; i <= cnt; i++) printf("%d%s", q[now][i], i != cnt ? ", " : ".\n"); } int main(void) { while(scanf("%d", &n), n != 0) work(); return 0; }