POJ 2318
計算幾何基礎,叉積的運用,及二分求解。
題目中保證了所有玩具都是在盒子內,並且不會位於邊界上。那麼利用叉積可以判斷出玩具相對於某個邊界的方向,逆時針則在該邊界左邊,順時針則在右邊。然後二分邊界,不斷做叉積,找出該點的具體在哪兩條邊界之間即可,找出具體位置後,該區域的玩具數加一。時間複雜度O(n*lg(m))。
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define mm0(a) memset(a,0,sizeof(a));
#define debug puts("It's ok here!")
using namespace std;
const int maxn=5e3+5;
struct Point{
int x, y;
Point(){}
Point(int _x, int _y):x(_x), y(_y){}
};
struct line{
Point s, t;
line(){}
line(int sx,int sy,int tx,int ty){s.x=sx; s.y=sy; t.x=tx; t.y=ty;}
line(Point _s, Point _t):s(_s), t(_t){}
};
bool crossleft(Point a,Point b,Point c){
return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x)>0;
}
Point toy[maxn];
line board[maxn];
int n, m;
int ans[maxn];
int query(int p){
int l=0, r=m+1;
while(l+1<r){
int mid=(l+r+1)>>1;
if(crossleft(board[mid].s,toy[p],board[mid].t))
r=mid;
else
l=mid;
}
return l;
}
int main()
{
int x1, y1, x2, y2;
int x, y;
int cas=0;
while(~scanf("%d",&m)&&m){
if(cas++!=0) puts("");
scanf("%d%d%d%d%d", &n, &x1, &y1, &x2, &y2);
board[0]=line(Point(x1,y1),Point(x1,y2));
board[m+1]=line(Point(x2,y1),Point(x2,y2));
for(int i=1;i<=m;i++){
scanf("%d%d",&x1, &x2);
board[i]=line(x1,y1,x2,y2);
}
for(int i=0;i<n;i++){
scanf("%d%d",&x, &y);
toy[i]=Point(x,y);
}
mm0(ans);
for(int i=0;i<n;i++){
int pos=query(i);
ans[pos]++;
}
for(int i=0;i<m+1;i++)
printf("%d: %d\n",i, ans[i]);
}
return 0;
}