我在算法竞赛从入门到进阶那里看的,通过做题还加了一些函数,觉得不错来看看吧!
#include <iostream> #include <algorithm> using namespace std; #define ll long long #define N 100005 #define eps 0.00000001//偏差值1e8 #define pi acos(-1.0)//高精度圆周率 const int maxp = 1010; //点的数量 int sgn(double x){ //判断x是否等于0 if (fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; } int Dcmp(double x, double y){ //比较两个浮点数:0为相等;-1为小于;1为大于 if (fabs(x - y) < eps)return 0; else return x < y ? -1 : 1; } //——————————————————平面几何:点和线———————————————————————— struct Point { //定义点及其基本运算 double x, y; Point() {} Point(double x, double y) :x(x), y(y) {} Point operator + (Point B) { return Point(x + B.x, y + B.y); } Point operator - (Point B) { return Point(x - B.x, y - B.y); } Point operator * (Point B) { return Point(x * B.x, y * B.y); } //长度增大k倍 Point operator / (Point B) { return Point(x / B.x, y / B.y); } //长度缩小k倍 bool operator ==(Point B) { return sgn(x - B.x) == 0 && sgn(y - B.y) == 0; } bool operator <(Point B) //比较两个点,用于凸包计算 { return sgn(x - B.x) < 0 || (sgn(x - B.x) == 0 && sgn(y - B.y) < 0); } }; typedef Point Vector; //定义向量 double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; } //点积 double Len(Vector A) { return sqrt(Dot(A, A)); } //向量的长度 double Len2(Vector A) { return Dot(A, A); } //向量长度的平方 //A与B的夹角 double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Len(A) / Len(B)); } double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; } //叉积 //三角形ABC面积的两倍 double Area2(Point A, Point B, Point C) { return Cross(B - A, C - A); } //两点的距离,用两种方式实现 double Distance(Point A, Point B) { return hypot(A.x - B.x, A.y - B.y); } double Dist(Point A, Point B){ return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y)); } //向量A的单位法向量 Vector Normal(Vector A) { return Vector(-A.y / Len(A), A.x / Len(A)); } //向量是否平行或重合 bool Parallel(Vector A, Vector B) { return sgn(Cross(A, B)) == 0; } Vector Rotate(Vector A, double rad) { //向量A逆时针旋转rad度 return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad)); } struct Line { //线上的两个点 Point p1, p2; Line(){} Line(Point p1,Point p2):p1(p1),p2(p2){} Line(Point p, double angle) { p1 = p; if (sgn(angle - pi / 2) == 0) { p2 = (p1 + Point(0, 1)); } else { p2 = (p1 + Point(1, tan(angle))); } } }; double mult(Point a, Point b, Point o) { /////计算叉乘 ao 和 bo return (a.x - o.x) * (b.y - o.y) >= (b.x - o.x) * (a.y - o.y); } int Graham(Point p[], int n, Point res[]) { //逆时针排序,构造凸包形状 int top = 1; sort(p, p + n); if (n == 0) return 0; res[0] = p[0]; if (n == 1) return 0; res[1] = p[1]; if (n == 2) return 0; res[2] = p[2]; for (int i = 2; i < n; i++) { while (top && (mult(p[i], res[top], res[top - 1]))) top--; res[++top] = p[i]; } int len = top; res[++top] = p[n - 2]; for (int i = n - 3; i >= 0; i--) { while (top != len && (mult(p[i], res[top], res[top - 1]))) top--; res[++top] = p[i]; } return top; } struct Polygon { int n; //多边形的顶点数 Point p[maxp]; //多边形的点 Line v[maxp]; //多边形的边 }; //点和线段的关系:0为点p不在线段v上;1为点p在线段v上 bool Point_on_seg(Point p, Line v) { return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <= 0; } //判断点和任意多边形的关系:3为点上;2为边上;1为内部;0为外部 int Point_in_polygon(Point pt, Point* p, int n) { int i; for (i = 0; i < n; i++) { if (p[i] == pt)return 3; } for (i = 0; i < n; i++) { Line v = Line(p[i],p[(i + 1) % n]); if (Point_on_seg(pt, v))return 2; } int num = 0; for (int i = 0; i < n; i++) { int j = (i + 1)%n; int c = sgn(Cross(pt - p[j], p[i] - p[j])); int u = sgn(p[i].y - pt.y); int v = sgn(p[j].y - pt.y); if (c > 0 && u < 0 && v >= 0)num++; if (c < 0 && u >= 0 && v < 0)num--; } return num != 0; }