1. 程式人生 > >【計算幾何+二分】 POJ 2318

【計算幾何+二分】 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');
	}
}