POJ 2653 Pick-up sticks【线段相交】

题意:n根木棍随意摆放在一个平面上,问放在最上面的木棍是哪些。

思路:线段相交,因为题目说最多有1000根在最上面。所以从后往前处理,直到木棍没了或者最上面的木棍的总数大于1000.

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
using namespace std;
const int N=1e5+111; 
const double eps=1e-8;
int sgn(double x){
    if(fabs(x)<eps)    return 0;
    if(x>0)    return 1;
    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.x+y*b.y;
    }
    double operator ^(const point &b)const{
        return x*b.y-y*b.x;
    }
};
struct line{
    point s,e;
    line(){}
    line(point s_,point e_){
        s=s_,e=e_;
    }
}li[N];
double cal(point p0,point p1,point p2){//叉积 
    return (p1-p0)^(p2-p0);
}
int xj(line a,line b){//判断两线段是否相交 
    point A=a.s,B=a.e,C=b.s,D=b.e;
    return 
    max(A.x,B.x)>=min(C.x,D.x) &&
    max(C.x,D.x)>=min(A.x,B.x) &&
    max(A.y,B.y)>=min(C.y,D.y) &&
    max(C.y,D.y)>=min(A.y,B.y) &&
    sgn(cal(A,C,D))*sgn(cal(B,C,D))<=0 &&
    sgn(cal(C,A,B))*sgn(cal(D,A,B))<=0;
}
int ans[N];
int main(){
    int n,i,j,js;
    while(~scanf("%d",&n)&&n){
        double x1,x2,y1,y2;js=0;
        for(i=1;i<=n;i++){
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            li[i]=line(point(x1,y1),point(x2,y2));
        }
        for(i=n;i&&js<1000;i--){
            for(j=i+1;j<=n;j++){
                if(xj(li[i],li[j]))
                    break;
            }
            if(j>n)    ans[++js]=i;
        }
        printf("Top sticks:");
        for(i=js;i;i--){
            printf(" %d%c",ans[i],i==1?'.':',');
        }
        puts("");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/L-King/p/5734194.html