POJ - 2318 TOYS(叉积+二分)

题目链接:点击查看

题目大意:给出一个盒子,由n条互不相交的线段分割为n+1个空格,现在有m个玩具的坐标,现在问每个空格内有多少个玩具

题目分析:利用叉积的性质判断点在直线的哪一侧:

 以点在直线左侧为例,对于一个点来说,n条线段就具有了单调性,以此二分找到该点右边的直线,则就确定了当前点所在的空格了

代码:

#include<iostream>
#include<cstdio> 
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
 
typedef long long LL;
 
const int inf=0x3f3f3f3f;

const int N=5e3+100;

int ans[N];

struct Point{
	double x,y;
	Point(){}
	Point(double _x,double _y){
		x = _x;
		y = _y;
	}
	void input(){
		scanf("%lf%lf",&x,&y);
	}
	Point operator -(const Point &b)const{
		return Point(x-b.x,y-b.y);
	}
	//叉积
	double operator ^(const Point &b)const{
		return x*b.y - y*b.x;
	}
	//点积
	double operator *(const Point &b)const{
		return x*b.x + y*b.y;
	}
}point[N];

struct Line{
	Point s,e;
	Line(){}
	Line(Point _s,Point _e){
		s = _s;
		e = _e;
	}
}line[N];

int xmult(Point p0,Point p1,Point p2)// ans>0左边 ans<0右边 
{
	return (p1-p0)^(p2-p0);
}

int main()
{
//	freopen("input.txt","r",stdin);
//	ios::sync_with_stdio(false);
	int n,m,x1,y1,x2,y2;
	while(scanf("%d",&n)!=EOF&&n)
	{
		scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
		for(int i=0;i<n;i++)
		{
			int u,l;
			scanf("%d%d",&u,&l);
			line[i]=Line(Point(u,y1),Point(l,y2));
		}
		line[n]=Line(Point(x2,y1),Point(x2,y2));
		memset(ans,0,sizeof(ans));
		while(m--)
		{
			Point p;
			p.input();
			int l=0,r=n,mark;
			while(l<=r)
			{
				int mid=l+r>>1;
				if(xmult(p,line[mid].s,line[mid].e)<0)
				{
					mark=mid;
					r=mid-1;
				}
				else
					l=mid+1;
			}
			ans[mark]++;
		}
		for(int i=0;i<=n;i++)
			printf("%d: %d\n",i,ans[i]);
		printf("\n");
	}
 
 
 
 
 
 
 
	
	
	
	
	
	
	
	
	
	return 0;
}
发布了577 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104092398