poj 2318 题解
题意:给出一个箱子四个点的坐标和n个已经排好序的不相交的隔板,隔板不相交,将箱子分隔,再给出m个点(点不在隔板上),求每个区域内有几个点
多组数据,n<=5000,m<=5000
题解:二分+叉积判断点是否在直线右边
注意:由题中Hint,在箱子右边界上的点算作最后一个区域的点;题中没给出坐标数据范围,直接用了long long
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) const double eps=1e-8; struct point{ double x,y; point(){} point (double a,double b): x(a),y(b) {} friend point operator + (const point &a,const point &b){ return point(a.x+b.x,a.y+b.y); } friend point operator - (const point &a,const point &b){ return point(a.x-b.x,a.y-b.y); } friend bool operator == (const point &a,const point &b){ return (abs(a.x-b.x)<eps && abs(a.y-b.y)<eps); } }; inline double det(point a,point b) {return a.x*b.y-a.y*b.x;} inline bool line_cross_segment(point s,point t,point a,point b) { return det(s-a,t-a)*det(s-b,t-b)<eps; } point s[200][2]; double sx,sy,tx,ty; int t,n; bool test(int x,int y) { point ts,tt; bool flag=false; rep(i,0,1) rep(j,0,1) if (!(s[x][i]==s[y][j])) { flag=true; ts=s[x][i];tt=s[y][j]; rep(k,1,n) if (!line_cross_segment(ts,tt,s[k][0],s[k][1])) { flag=false; break; } if (flag) break; } if (flag) return true; else return false; } int main() { scanf("%d",&t); bool flag; while (t--) { scanf("%d",&n); flag=false; rep(i,1,n) { scanf("%lf%lf%lf%lf",&sx,&sy,&tx,&ty); s[i][0]=point(sx,sy);s[i][1]=point(tx,ty); } if (n<=2) {printf("Yes!\n");continue;} rep(i,1,n) rep(j,i+1,n) if(test(i,j)) {flag=true;break;} if (flag) printf("Yes!\n");else printf("No!\n"); } return 0; }