【计算几何+二分】 POJ 2318

虚空传送门

【题目大意】给定一个箱子的左上角坐标和右上角坐标。给定n个隔板的端点坐标【保证隔板不相交】,内部隔间从0到n编号。

给定m个玩具的坐标【保证玩具在箱子内部且不在隔板上】,每个玩具在一个隔间内。

问每个隔间内有多少个玩具。

首先用叉积判玩具在隔板的哪个方位。我们利用二分找到玩具右边的第一个隔板,然后把这个隔间的答案加一。

具体有些细节看代码吧。

#include<cstdio>
#include<cstring>
using namespace std;
struct point{
	int x,y;
	point(int _x=0,int _y=0){x=_x,y=_y;}
	friend inline int operator *(const point &a,const point &b){
		return a.x*b.y-a.y*b.x;
	}
	friend inline point operator +(const point &a,const point &b){
		return point(a.x+b.x,a.y+b.y);
	}
	friend inline point operator -(const point &a,const point &b){
		return point(a.x-b.x,a.y-b.y);
	}
}toy,up[10000],down[10000],U,D;
int ans[233333],n,m;

//a is toy
//(b->a)*(b->c)
//如果玩具在隔板bc的左边,返回真,否则返回假。 
bool check(point a,point b,point c){
	return (c-b)*(a-b)>0;
}
int main(){
	while(scanf("%d",&n)&&n){
		memset(ans,0,sizeof(ans));
		scanf("%d",&m);
		scanf("%d%d%d%d",&U.x,&U.y,&D.x,&D.y);
		for(int i=1;i<=n;++i){
			scanf("%d%d",&up[i].x,&down[i].x);
			up[i].y=U.y,down[i].y=D.y;
		}
		for(int i=1;i<=m;++i){
			scanf("%d%d",&toy.x,&toy.y);
			//注意二分的上下界。 
			int l=1,r=n+1;
			while(l<r){
				int mid=(l+r)>>1;
				if(check(toy,down[mid],up[mid]))
					r=mid;
				else l=mid+1;
			}
			
			//注意隔间的编号。第L个隔板左边对应第L-1个隔间。 
			ans[l-1]++;
		}
		for(int i=0;i<=n;++i)
			printf("%d: %d\n",i,ans[i]);
		
		putchar('\n');
	}
}

猜你喜欢

转载自blog.csdn.net/g21wcr/article/details/83098137
今日推荐