POJ 2653 Pick-up sticks(线段规范相交)
http://poj.org/problem?id=2653
题意: ZOJ2551
有n根厚度忽略不计的木棍平行的往地板按顺序扔,扔完之后给你每根木棍在地板这个二维平面的端点坐标,要你输出那些木棍是在最上面的(即没有任何一根木棍压着它).
用例的图,木棍2压着木棍1了.
分析:
本题直接暴力解决即可.由于木棍是按顺序扔下去的,那么只要在当前木棍后面扔的所有木棍都是有可能压着它的. 所以我们依次遍历当前木棍之后放的所有木棍即可.
(判断木棍是否被压,只要看这两个木棍是否规范相交即可)
用的依然是刘汝佳 线段规范相交的模板.
这个貌似不能优化的,
AC代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const double eps=1e-10; int dcmp(double x) { if(fabs(x)<eps) return 0; return x<0?-1:1; } struct Point { double x,y; Point(){} Point(double x,double y):x(x),y(y){} }; typedef Point Vector; Vector operator-(Point A,Point B) { return Vector(A.x-B.x, A.y-B.y); } double Cross(Vector A,Vector B) { return A.x*B.y-A.y*B.x; } bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2) { double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1); double c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1); return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0; } const int maxn=100000+5; int n; Point P[maxn],Q[maxn]; bool up[maxn];//标记该线段是否在最上面 int main() { while(scanf("%d",&n)==1 && n) { for(int i=1;i<=n;++i) scanf("%lf%lf%lf%lf",&P[i].x,&P[i].y,&Q[i].x,&Q[i].y),up[i]=true; for(int i=1;i<=n;++i) { for(int j=i+1;j<=n;++j) if(SegmentProperIntersection(P[i],Q[i],P[j],Q[j])) { up[i]=false; break; } } int i; for(i=1;i<=n;++i)if(up[i])break; printf("Top sticks: %d",i); for(++i;i<=n;++i)if(up[i]) printf(", %d",i); printf(".\n"); } return 0; }