【POJ 2318】TOYS(二分+叉积)
设点a 假如a在一个板子1的左边 那他肯定也在一个板子2左边 而且板子还是按顺序排的
满足单调性 可以二分
考虑check 判断点a在直线L左边 只需判断a到直线L的端点1 端点2两个向量的叉积小不小于0
#include<iostream> #include<cmath> #include<iomanip> #include<cstdio> #include<cstring> #define eps 1e-6 #define N 5005 using namespace std; struct Point { double x,y; Point(double x=0,double y=0):x(x),y(y){}; }p[N]; typedef Point Vector; Vector operator +(Vector a,Vector b) { return Vector(a.x+b.x,a.y+b.y); } Vector operator -(Vector a,Vector b) { return Vector(a.x-b.x,a.y-b.y); } Vector operator *(Vector a,double p) { return Vector(a.x*p,a.y*p); } Vector operator /(Vector a,double p) { return Vector(a.x/p,a.y/p); } bool operator <(const Vector &a,const Vector &b) { return a.x<b.x||(a.x==b.x)&&(a.y<b.y); } double Dot(Vector a,Vector b)//点积 { return a.x*b.x+a.y*b.y; } double Len(Vector a) { return sqrt(Dot(a,a)); } double Angle(Vector a,Vector b)//夹角 { return acos(Dot(a,b)/Len(a)/Len(b)); } double Cross(Vector a,Vector b) { return a.x*b.y-a.y*b.x; } int dcmp(double x) { if(fabs(x)<eps) return 0; else return x<0?-1:1; } struct Line { Point p1,p2; Line(){}; Line(Point p1,Point p2):p1(p1),p2(p2){} }l[N]; int n,m; Point upper_left,lower_right; inline bool PointIsLeft(Point p,Line k) { Vector v1=k.p1-p; Vector v2=k.p2-p; return dcmp(Cross(v1,v2))<0; } inline int BinarySearch(Point p) { int le=0,ri=n-1; while(le<=ri) { int m=(le+ri)>>1; if(PointIsLeft(p,l[m])) ri=m-1; else le=m+1; } return le; } int ans[N]; int main() { while(true) { cin>>n; if(!n) break; cin>>m>>upper_left.x>>upper_left.y>>lower_right.x>>lower_right.y; double x1,x2; for(int i=0;i<n;i++) { cin>>x1>>x2; Point p1=Point(x1,upper_left.y); Point p2=Point(x2,lower_right.y); l[i]=Line(p1,p2); } memset(ans,0,sizeof(ans)); for(int i=0;i<m;i++) { cin>>p[i].x>>p[i].y; int a=BinarySearch(p[i]); //cout<<a<<endl; ans[a]++; } for(int i=0;i<n+1;i++) { cout<<i<<": "<<ans[i]<<'\n'; } cout<<'\n'; } }
QQ40523591~欢迎一起学习交流~