1. 向量的基本运算
1.1点和向量的表示
在平面直角坐标系中,任意一点的坐标可以用一个有序数对 (x,y) 表示,向量也是如此
struct Point//点或向量
{
double x, y;
Point() {}
Point(double x, double y) :x(x), y(y) {}
};
typedef Point Vector;
1.2基本向量运算
设向量 v1=(x1,y1),v2=(x2,y2) ,定义如下运算
1.2.1 向量四则运算以及向量的模长
int dcmp(double x)//精度三态函数(>0,<0,=0)
{
if (fabs(x) < eps)return 0;
else if (x > 0)return 1;
return -1;
}
Vector operator + (Vector a, Vector b)//向量加法
{
return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b)//向量减法
{
return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, double p)//向量数乘
{
return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, double p)//向量数除
{
return Vector(a.x / p, a.y / p);
}
double Distance(Point a, Point b)//两点间距离
{
return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
bool operator == (const Point &a, const Point &b)//向量相等
{
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
2.向量的叉积的运用
叉积的方向
2.1.叉积的几何意义:
double Cross(Vector a, Vector b)//外积
{
return a.x*b.y - a.y*b.x;
}
2.2叉积的运用:
2.2.1计算多边形的面积
2.2.2判断凹凸多边形
2.2.3折线的拐向的方向
2.2.4:判断点是否在线段上
代码模板
struct line//线段
{
Point s;
Point e;
line(Point s, Point e){s = a, e = b;}
line(){}
}
//直线方程
struct Lineequ
{
double a, b, c;
Lineequ(double a1, double b1, double c1)
{a = a1; b = b1; c = c1;}
Lineequ(){}
}
double Cross(Vector a, Vector b)//外积
{
return a.x*b.y - a.y*b.x;
}
double Dot(Vector a, Vector b)//内积
{
return a.x*b.x + a.y*b.y;
}
//判断是否在线段上
bool InSegment(Point P,Point A,Point B)
{
return dcmp(Cross(A-B,P-A))==0 && dcmp(Dot(A-P,B-P))<=0;
}
2.2.5:判断两个线段是否相交
bool StrictIntersect(Point A, Point B, Point C, Point D) //线段相交(包括端点)
{
return
dcmp(max(A.x, B.x) - min(C.x, D.x)) >= 0
&& dcmp(max(C.x, D.x) - min(A.x, B.x)) >= 0
&& dcmp(max(A.y, B.y) - min(C.y, D.y)) >= 0
&& dcmp(max(C.y, D.y) - min(A.y, B.y)) >= 0
&& dcmp(Cross(C - A, D - A)*Cross(C - B, D - B)) <= 0
&& dcmp(Cross(A - C, B - C)*Cross(A - D, B - D)) <= 0;
}
2.2.6判断点是否在多边形中
HDU1756;
#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define next Next
#define f first
#define s second
using namespace std;
const int N = 500 + 10;
const double eps = 1e-9;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
struct Point//点或向量
{
double x, y;
Point() {}
Point(double x, double y) :x(x), y(y) {}
};
typedef Point Vector;
int dcmp(double x)//精度三态函数(>0,<0,=0)
{
if (fabs(x) < eps)return 0;
else if (x > 0)return 1;
return -1;
}
double Dot(Vector a, Vector b)//内积
{
return a.x*b.x + a.y*b.y;
}
Vector operator + (Vector a, Vector b)//向量加法
{
return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b)//向量减法
{
return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, double p)//向量数乘
{
return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, double p)//向量数除
{
return Vector(a.x / p, a.y / p);
}
double Distance(Point a, Point b)//两点间距离
{
return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
bool operator == (const Point &a, const Point &b)//向量相等
{
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
double Cross(Vector a, Vector b)//外积
{
return a.x*b.y - a.y*b.x;
}
bool InSegment(Point P,Point A,Point B)
{
return dcmp(Cross(A-B,P-A))==0 && dcmp(Dot(A-P,B-P))<=0;
}
int IsPointInPolygon(Point p,Point *poly,int n)
{
int wn=0;
for(int i=0;i<n;++i)
{
if(InSegment(p, poly[(i+1)%n], poly[i]) ) return 1;
int k=dcmp( Cross(poly[(i+1)%n]-poly[i], p-poly[i] ) );
int d1=dcmp( poly[i].y-p.y );
int d2=dcmp( poly[(i+1)%n].y-p.y );
if(k>0 && d1<=0 && d2>0) ++wn;
if(k<0 && d2<=0 && d1>0) --wn;
}
if(wn != 0) return 1;
return 0;
}
int npoi, nploy;
Point ploy[1100];
int main()
{
IOS;
while(cin >> nploy)
{
_for(i,0,nploy)
{
double x,y;
cin >> x >> y;
ploy[i] = {x,y};
}
cin >> npoi;
while(npoi --)
{
double x, y;
cin >> x >> y;
if(IsPointInPolygon({x,y},ploy,nploy)) puts("Yes");
else puts("No");
}
}
return 0;
}
3.向量的点积
向量点积的几何意义:就是 a ∗ b = b 在 a 方 向 上 投 影 的 大 小 a*b=b在a方向上投影的大小 a∗b=b在a方向上投影的大小
3.1定义:r = AP/AB
则r = ac dot(点乘) ab / |ab|^2
下面A,B是线段两个端点
double relation(Point A, Point B, Point C)
{
return Dot(B - A, C - A) / Distance(A,B) / Distance(A,B);
}
求C在AB所在直线的垂足P坐标
Point pedal(Point A, Point B, Point C)
{
double r = relation(A,B,C);
Point res;
res.x = A.x + r * (B.x - A.x);
res.y = A.y + r * (B.y - A.y);
return res;
}
求直线外一点距离直线线段最近距离
double pedaldist(Point A, Point B, Point C)
{
double r = relation(A,B,C);
if(r < 0) return Distance(A,C);
else if(r > 1) return Distance(B,C);
else
{
Point np = pedal(A,B,C);
return Distance(np,C);
}
}
double DistanceToLine(Point A, Point M, Point N)//点A到直线MN的距离,Error:MN=0
{
return fabs(Cross(A - M, A - N) / Distance(M, N));
}
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w)//两直线的交点
{
Vector u = P - Q;
double t = Cross(w, u) / Cross(v, w);
return P + v * t;
}