POJ 2653 Pick-up sticks

线段相交判断

/*
    链表维护 n^2算法?
*/
#include<cstdio>

#include<algorithm>

using namespace std;

const int N=1e5+50;

const double eps=1e-9;

struct Point
{
    double x,y; Point(){}
    Point(double _x,double _y){x=_x,y=_y;}
};

Point operator - (Point A,Point B) {return Point(A.x-B.x,A.y-B.y);} 

double operator ^ (Point A,Point B) {return A.x*B.y-A.y*B.x;} 

double cross(Point a,Point b,Point c) {return (a-c)^(b-c);} 

struct Line
{
    Point s,e; Line(){}
    Line(Point _s,Point _e){s=_s,e=_e;}
}L[N];

int nxt[N],pre[N],n,sta[N],top;

void cut(int x) {nxt[pre[x]]=nxt[x],pre[nxt[x]]=pre[x];} 

bool check(Line l1,Line l2) // 线段相交的判断。。有点累赘
{
    if(min(l2.s.x,l2.e.x)>max(l1.s.x,l1.e.x)) return 0;
    if(min(l2.s.y,l2.e.y)>max(l1.s.y,l1.e.y)) return 0;
    if(min(l1.s.x,l1.e.x)>max(l2.s.x,l2.e.x)) return 0;
    if(min(l1.s.y,l1.e.y)>max(l2.s.y,l2.e.y)) return 0; 
// 相当于 左边线段的最大值都要比右边线段的最小值小 
// 或者是 上面线段的最小值比下面线段的最大值要大  一定没有交点
    if(cross(l1.s,l2.e,l2.s)*cross(l1.e,l2.e,l2.s)>eps) return 0;
    if(cross(l2.s,l1.e,l1.s)*cross(l2.e,l1.e,l1.s)>eps) return 0;
// 两种 跨立实验
    return 1; //排除不相交的情况 剩下就相交了
}

int main()
{
    while(scanf("%d",&n)&&n)
    {
        for(int i=1;i<=n;i++)
        {
            double x,y;Point a,b;
            scanf("%lf%lf",&x,&y);a=Point(x,y);
            scanf("%lf%lf",&x,&y);b=Point(x,y);
            L[i]=Line(a,b); nxt[i]=i+1; pre[i]=i-1;
        }
        nxt[0]=1; pre[n+1]=n;
        for(int i=1;i<=n;i++)
            for(int j=nxt[0];j<i;j=nxt[j])
                if(check(L[i],L[j])) cut(j);
        top=0; for(int i=nxt[0];i<=n;i=nxt[i]) sta[++top]=i;
        printf("Top sticks: %d",sta[1]);
        for(int i=2;i<=top;i++) printf(", %d",sta[i]);puts(".");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lxy8584099/p/10419372.html