【计算几何】【叉积】poj2318
开始过计算几何部分。看到一篇题目集锦,打算接下来的时间按照博客来做:https://blog.csdn.net/yang_7_46/article/details/8525631
题目链接:https://vjudge.net/problem/POJ-2318
题意:给了m个点,落在n+1个区域中,问各个区域有多少个点。
做法:就是叉积的运用,我们cross(Point o,Point a,Point b)代表向量oa和ob的叉积(代表oa到ob的夹角),叉积为正,则代表oa到ob的角为正,则点a在点b的顺时针方向(因为逆时针的角为正)。反之同理。
所以利用这条性质可以判断点在直线的左边还是右边,直接二分答案ok。
代码如下:
1 /************************************************************************* 2 > File Name: poj2318.cpp 3 # File Name: poj2318.cpp 4 # Author : xiaobuxie 5 # QQ : 760427180 6 # Email:760427180@qq.com 7 # Created Time: 2019年09月17日 星期二 17时08分28秒 8 ************************************************************************/ 9 10 #include<iostream> 11 #include<cstdio> 12 #include<map> 13 #include<cmath> 14 #include<cstring> 15 #include<set> 16 #include<queue> 17 #include<vector> 18 #include<algorithm> 19 using namespace std; 20 typedef long long ll; 21 #define inf 0x3f3f3f3f 22 #define pq priority_queue<int,vector<int>,greater<int> > 23 ll gcd(ll a,ll b){ 24 if(a<b) return gcd(b,a); 25 return b==0?a:gcd(b,a%b); 26 } 27 const int N=5e3+9; 28 struct Point{ 29 int x,y; 30 }p; 31 struct Line{ 32 Point s,t; 33 }L[N]; 34 int ans[N]; 35 int cross(Point o,Point a,Point b){ 36 return (o.x-a.x)*(o.y-b.y)-(o.x-b.x)*(o.y-a.y); 37 } 38 bool judge(int x){ 39 return cross(p,L[x].s,L[x].t)<=0; 40 } 41 int main(){ 42 int n,m,x1,x2,y1,y2; 43 while(~scanf("%d",&n) && n){ 44 memset(ans,0,sizeof(ans)); 45 scanf("%d",&m); 46 scanf("%d %d %d %d",&x1,&y1,&x2,&y2); 47 for(int i=0;i<n;++i){ 48 int u,l; scanf("%d %d",&u,&l); 49 L[i]=(Line){ (Point){u,y1}, (Point){l,y2}}; 50 } 51 L[n]=(Line){ (Point){x2,y1}, (Point){x2,y2}}; 52 while(m--){ 53 int x,y; 54 scanf("%d %d",&x,&y); 55 p=(Point){x,y}; 56 int l=0,r=n,res; 57 while(l<=r){ 58 int m=(l+r)>>1; 59 if(judge(m)){ 60 res=m; 61 r=m-1; 62 } 63 else l=m+1; 64 } 65 ans[res]++; 66 } 67 for(int i=0;i<=n;++i) printf("%d: %d\n",i,ans[i]); 68 printf("\n"); 69 } 70 return 0; 71 }