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; }