POJ2653->判断线段相交
题意:
有一些线段,按顺序给出,后给出的线段可能会覆盖住先给出的线段,求这些线段中最后没有被覆盖住的线段的编号。
题解:
一次输入所有线段后,枚举编号1-n,用跨立实验去验证每条线段有没有被后面的线段覆盖,一旦查询到有编号大于它的线段跨立它,则跳出当前循环。
代码:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <cmath>
using namespace std ;
#define MAX 100010
bool flag[MAX] ;
const double eps = 1e-8;
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 ;
Line(){}
Line(Point _s , Point _e)
{
s = _s ; e = _e ;
}
};
Line line[MAX] ;
//判断线段相交
bool inter(Line l1,Line l2)
{
return
max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s)) <= 0 &&
sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s)) <= 0;
}
int main()
{
int n;
while(scanf("%d" , &n)!= EOF , n)
{
double x1,x2,y1,y2 ;
memset(flag , false , sizeof(flag)) ;
for(int i = 0 ; i < n ; i ++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[i] = Line(Point(x1,y1),Point(x2,y2));
}
for(int i = 0 ; i < n ; i ++)
{
for(int j = i + 1 ; j < n ; j ++)
{
if(inter(line[i] , line[j]))
{
flag[i] = true ;
break ;
}
}
}
printf("Top sticks:") ;
int temp = 0 ;
for(int i = 0 ; i < n ; i ++)
{
if(!flag[i])
{
if(temp == 0)
{
printf(" %d" , i+1) ;
temp = 1 ;
}
else printf(", %d" , i+1) ;
}
}
printf(".\n") ;
}
return 0 ;
}