第一道计算几何题。。
题意:
在一个长方形盒子中被线段划分成了几段区域,然后每段区域中都有一些物品,让你判断在每个区域中分别有几个物品。
叉积的简单应用:
这就要用到向量叉积。叉积的一个非常重要的性质是通过它的符号判断两向量相互之间的顺逆时针关系:设向量P=(x1,y1),Q=(x2,y2)
如果P*Q>0则P在Q的顺时针方向;
如果P*Q=0则P与Q共线,可能同向,与可能反向;
如果P*Q<0则P在Q的逆时针方向。
(请注意这里是叉乘)
这里要注意一点就是我们在做叉积的时候,要先选择好是按照下面还是按照上面部分作为起始点。也就是在算向量时的起始点。要不然的话会使叉积的顺时针或是逆时针不同,这样就会使答案不一样了。
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<iostream>
#include<time.h>
using namespace std;
typedef __int64 ll;
typedef unsigned __int64 ULL;
#define pi acos(-1.0)
#define Ex exp(1.0)
#define maxn 5050*2
int vis[5050];
struct node{
int x,y,idx;
}a[maxn],b[maxn];
struct Point{
int x,y;
Point(int x=0,int y=0):x(x),y(y){}
};
typedef Point Vector;
Vector operator - (Point A,Point B){
return Vector(A.x-B.x,A.y-B.y);
}
Vector operator * (Point A,double p){
return Vector(A.x*p,A.y*p);
}
int Cross(Vector A,Vector B){
return A.x*B.y-A.y*B.x;
}
int main(){
int n,m,x1,y1,x2,y2;
while(~scanf("%d",&n)){
if(n==0) break;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
for(int i=1;i<=n;i++){
int u,v;
scanf("%d%d",&u,&v);
a[i].x=u,a[i].y=y1,a[i+5000].x=v,a[i+5000].y=y2;
//我这里是选择了y1作为下面,也就是向量的起始点,要不然会导致错误
//因为如果不统一的话会导致一会儿以上面的点算为起始点,一会儿以下面的点作为起始点
//从而导致叉积的不同,从而导致无法统一方向。
swap(a[i].x,a[i+5000].x);
swap(a[i].y,a[i+5000].y);
}
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
b[i].x=u,b[i].y=v;
}
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(vis[j]) continue;
Vector A,B,C;
A.x=a[i].x;
A.y=a[i].y;
B.x=a[i+5000].x;
B.y=a[i+5000].y;
C.x=b[j].x;
C.y=b[j].y;
C=C-A;
A=B-A;
if(Cross(C,A)>0){
if(i==n){
vis[j]=1;
a[i].idx++;
continue;
}
Vector D,E,F;
D.x=a[i+1].x;
D.y=a[i+1].y;
E.x=a[(i+1)+5000].x;
E.y=a[(i+1)+5000].y;
F.x=b[j].x;
F.y=b[j].y;
F=F-D;
D=E-D;
if(Cross(F,D)<0){
vis[j]=1;
a[i].idx++;
}
}
else if(Cross(C,A)<=0){
if(i==1){
vis[j]=1;
a[i-1].idx++;
continue;
}
Vector D,E,F;
D.x=a[i-1].x;
D.y=a[i-1].y;
E.x=a[(i-1)+5000].x;
E.x=a[(i-1)+5000].y;
F.x=b[j].x;
F.y=b[j].y;
F=F-D;
D=E-D;
if(Cross(F,D)>0){
vis[j]=1;
a[i-1].idx++;
}
}
}
}
for(int i=0;i<=n;i++){
printf("%d: %d\n",i,a[i].idx);
}
printf("\n");
}
#ifndef ONLINE_JUDGE
system("pause");
#endif
return 0;
}
/*
5 6 0 10 60 0
3 1
4 3
6 8
10 10
15 30
1 5
2 1
2 8
5 5
40 10
7 9
*/