题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=3132
本题学习计算几何基础:叉积
我们怎么去判断一个点在一条线段的左侧还是右侧呢?
这就要用到向量叉积。叉积的一个非常重要的性质是通过它的符号判断两向量相互之间的顺逆时针关系:设向量P=(x1,y1),Q=(x2,y2)
如果P*Q>0则P在Q的顺时针方向;即:x1*y2 - x2*y1>0
如果P*Q=0则P与Q共线,可能同向,与可能反向;即:x1*y2 - x2*y1=0
如果P*Q<0则P在Q的逆时针方向。即:x1*y2 - x2*y1<0
如何已知两个点坐标,求其向量是简单的
另外利用二分法实现查找:
#include <stdio.h> #include <stdlib.h> #include <iostream> #include <string.h> #include <algorithm> using namespace std; #define maxn 100002 typedef struct { int x1; int y1; int x2; int y2; } NArray; NArray nArray[maxn]; int numArray[maxn]; int x,y,n,m; bool cmp(int a,int b) { return a>b; } bool cmp1(NArray a,NArray b) { return a.x1<b.x1; } //true代表右边,false代表左边 bool judge(int e,int px,int py) { return (long long)(px - nArray[e].x2) * (long long)(nArray[e].y1 - nArray[e].y2) > (long long)(nArray[e].x1 - nArray[e].x2) * (long long)(py - nArray[e].y2); } //二分 void add(int px,int py) { if(judge(n,px,py)) { numArray[n+1]++; return; } int a = 1; int b = n; while(a<b) { int mid = (a+b)/2; if(!judge(mid,px,py)) { b = mid; } else { a = mid + 1; } } numArray[a]++; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif int px,py; while(scanf("%d %d %d %d",&x,&y,&n,&m)!=EOF) { memset(numArray,0,sizeof(numArray)); for(int i=1; i<=n; i++) { scanf("%d %d",&nArray[i].x1,&nArray[i].x2); nArray[i].y1 = y; nArray[i].y2 = 0; } sort(nArray+1,nArray+n+1,cmp1); for(int i=1; i<=m; i++) { scanf("%d %d",&px,&py); add(px,py); } sort(numArray+1,numArray+n+2,cmp); for(int j=1; j<=4; j++) { printf("%d ",numArray[j]); } printf("%d\n",numArray[5]); } return 0; }