题意:有些人没事儿喜欢往地上任棍子,后面扔的可能盖住前面扔的,显然最后扔的那根棍子一定没被压住,求所有没有被其它棍子压住的棍子。
题解:规范相交。用链表优化下。当然也可以用队列存储下标。
#include<cmath>
#include<iostream>
using namespace std;
#define eps 1e-8
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
struct Point { double x, y; };
struct Line { Point a, b; };
struct NODE
{
Line l;
int id;
NODE *next, *pre;
} node[200000];
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 opposite_side ( Point p1, Point p2, Point l1, Point l2 )
{
return xmult ( l1, p1, l2 ) * xmult ( l1, p2, l2 ) < -eps;
}
int intersect_ex ( Line u, Line v )
{
if ( max(u.a.x, u.b.x) > min(v.a.x, v.b.x) &&
max(v.a.x, v.b.x) > min(u.a.x, u.b.x) &&
max(u.a.y, u.b.y) > min(v.a.y, v.b.y) &&
max(v.a.y, v.b.y) > min(u.a.y, u.b.y) &&
opposite_side ( u.a, u.b, v.a, v.b ) &&
opposite_side ( v.a, v.b, u.a, u.b ) )
return 1;
return 0;
}
void insert ( NODE *& last, NODE *nod )
{
nod->pre = last;
nod->next = NULL;
last->next = nod;
last = nod;
}
void del ( NODE *nod )
{
nod->next->pre = nod->pre;
nod->pre->next = nod->next;
}
int main()
{
int n;
while ( scanf("%d",&n) && n )
{
NODE first, *last, *p, *tmp;
first.next = NULL;
last = NULL;
for ( int i = 1; i <= n; i++ )
{
scanf("%lf %lf %lf %lf", &node[i].l.a.x, &node[i].l.a.y, &node[i].l.b.x, &node[i].l.b.y );
node[i].id = i;
if ( last == NULL )
{
last = &node[i];
last->next = NULL;
last->pre = &first;
first.next = last;
continue;
}
insert ( last, &node[i] );
p = last->pre;
while ( p != &first )
{
tmp = p->pre;
if ( intersect_ex ( last->l, p->l ) )
del ( p );
p = tmp;
}
}
printf("Top sticks: ");
p = first.next;
while ( p != NULL )
{
printf("%d",p->id);
if ( p->next == NULL )
printf(".\n");
else printf(", ");
p = p->next;
}
}
return 0;
}