叉乘原理
它可以用来判断点在直线的某侧。进而可以解决点是否在三角形内,两个矩形是否重叠等问题。向量的叉积的模表示这两个向量围成的平行四边形的面积。
设矢量P = ( x1, y1 ),Q = ( x2, y2 ),则矢量叉积定义为由(0,0)、p1、p2和p1+p2所组成的平行四边形的带符号的面积,即:P×Q = x1y2 - x2y1,其结果是一个伪矢量。
显然有性质 P × Q = - ( Q × P ) 和 P × ( - Q ) = - ( P × Q )。
叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:
若 P × Q > 0 , 则P在Q的顺时针方向。
若 P × Q < 0 , 则P在Q的逆时针方向。
若 P × Q = 0 , 则P与Q共线,但可能同向也可能反向。
叉积的方向与进行叉积的两个向量都垂直,所以叉积向量即为这两个向量构成平面的法向量。
如果向量叉积为零向量,那么这两个向量是平行关系。
因为向量叉积是这两个向量平面的法向量,如果两个向量平行无法形成一个平面,其对应也没有平面法向量。所以,两个向量平行时,其向量叉积为零。
利用叉乘来判断点与直线位置关系
传送门
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n ,m ,tx,ty,x2,y2 ;
const int maxn = 5000+100;
struct node
{
int x , y;
// bool operator < (const node &a)const
// {
// if(x!=a.x)return x< a.x;
// return y < a.y;
// }
}g[maxn];
int u[maxn],l[maxn],cnt[maxn];
int ju(int a,int b,node d)
{
if(((d.x-a)*(y2-ty)-(b-a)*(d.y-ty))<0)
return -1;
else return 1;
}
int main()
{
int kase = 1;
while(cin >> n&&n)
{
if(kase++ >1)printf("\n");
memset(cnt,0,sizeof(cnt));
memset(l,0,sizeof(l));
memset(u,0,sizeof(u));
memset(g,0,sizeof(g));
cin >> m>>tx>>ty>>x2>>y2;
for(int i=0;i<n;i++) cin >> u[i]>>l[i];
for(int i=0;i<m;i++) cin >> g[i].x>>g[i].y;
// sort(g,g+m);
int sum = 0 , j;
// cout << ty<<" "<< y2<<endl;
for(int i=0;i<m;i++)
{
if(ju(u[0],l[0],g[i])>0){cnt[0]++;sum++;continue;}
for(j=0;j<n-1;j++)
{
if(ju(u[j],l[j],g[i])<0&&ju(u[j+1],l[j+1],g[i])>0)
{
cnt[j+1]++;
sum++;
}
}
}
cnt[n] = m-sum;
for(int i=0;i<=n;i++)
{
printf("%d: %d\n",i,cnt[i]);
}
}
return 0;
}