寄蒜几盒?
1 struct Poi { 2 LL x, y; 3 Poi() {} 4 Poi(LL X, LL Y) 5 : x(X), y(Y) {} 6 bool operator==(const Poi& R) const { 7 return (x == R.x) && (y == R.y); 8 } 9 Poi operator+(const Poi& R) const { 10 return Poi(x + R.x, y + R.y); 11 } 12 Poi operator-(const Poi& R) const { 13 return Poi(x - R.x, y - R.y); 14 } 15 LL operator&(const Poi& R) const { 16 return x * R.x + y * R.y; 17 } 18 LL operator*(const Poi& R) const { 19 return x * R.y - y * R.x; 20 } 21 inline void read() { 22 ::read(x); 23 ::read(y); 24 } 25 }; 26 struct Line { 27 Poi A, B; 28 Line() {} 29 Line(Poi a, Poi b) 30 : A(a), B(b) {} 31 }; 32 inline LL dis2(Poi A, Poi B) { 33 return (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y); 34 } 35 36 inline bool ConvexCmp(const Poi& A, const Poi& B) { 37 if(A.x != B.x) 38 return A.x < B.x; 39 return A.y < B.y; 40 } 41 void GetConvex(Poi* a, int n, Poi* p, int& tot) { 42 std::sort(a, a + n, ConvexCmp); 43 p[0] = a[0]; 44 tot = 1; 45 for(int i = 1; i < n; i++) { 46 while((tot > 1 && (p[tot - 1] - p[tot - 2]) * (a[i] - p[tot - 1]) <= 0)) { 47 --tot; 48 } 49 p[tot++] = a[i]; 50 } 51 int temp = tot; 52 for(int i = n - 2; i >= 0; i--) { 53 while((tot > temp && (p[tot - 1] - p[tot - 2]) * (a[i] - p[tot - 1]) <= 0)) { 54 --tot; 55 } 56 p[tot++] = a[i]; 57 } 58 --tot; 59 return; 60 }
如果要取实数绝对值,用fabs,c++98的abs不支持实数,返回的是整数。
------------------------------------------
直线用点 + 点表示。
向量叉积:得到的是平行四边形的面积。不满足交换律。
1 × 2 = (x1y2 - x2y1)
p × q以p为基准,若q在逆时针方向,则叉积为正。
凸包:扫描。
大概就是先按照x排序,然后横着来回扫一遍,过去的时候得到下凸包,回来的时候得到上凸包。
如果叉积为负,就把当前的栈顶出栈。
模板题:洛谷P2742
1 /** 2 * by huyufeifei 3 */ 4 #include <cstdio> 5 #include <algorithm> 6 #include <cmath> 7 8 const int N = 100010; 9 const double eps = 1e-8; 10 11 struct Vec { 12 double x, y; 13 Vec(double X = 0, double Y = 0) { 14 x = X; 15 y = Y; 16 } 17 inline double operator *(const Vec &w) const { 18 return x * w.y - w.x * y; 19 } 20 inline double operator &(const Vec &w) const { 21 return x * w.x + y * w.y; 22 } 23 inline Vec operator -(const Vec &w) const { 24 return Vec(x - w.x, y - w.y); 25 } 26 inline bool operator <(const Vec &w) const { 27 if(fabs(x - w.x) > eps) { 28 return x < w.x; 29 } 30 return y < w.y; 31 } 32 }; 33 typedef Vec Poi; 34 35 inline double Len(Vec a) { 36 return sqrt(a & a); 37 } 38 39 inline int getConvex(int n, Poi *a, Poi *p) { 40 std::sort(a + 1, a + n + 1); 41 int top = 1; 42 p[1] = a[1]; 43 for(int i = 2; i <= n; i++) { 44 while(top > 1 && (p[top] - p[top - 1]) * (a[i] - p[top]) <= 0) { 45 top--; 46 } 47 p[++top] = a[i]; 48 } 49 int t = top; 50 for(int i = n - 1; i >= 1; i--) { 51 while(top > t && (p[top] - p[top - 1]) * (a[i] - p[top]) <= 0) { 52 top--; 53 } 54 p[++top] = a[i]; 55 } 56 top--; 57 return top; 58 } 59 60 Poi a[N], b[N]; 61 62 int main() { 63 64 int n; 65 scanf("%d", &n); 66 for(int i = 1; i <= n; i++) { 67 scanf("%lf%lf", &a[i].x, &a[i].y); 68 } 69 int t = getConvex(n, a, b); 70 double ans = 0; 71 for(int i = 2; i <= t; i++) { 72 ans += Len(b[i] - b[i - 1]); 73 } 74 ans += Len(b[1] - b[t]); 75 printf("%.2f\n", ans); 76 77 return 0; 78 }
线段相交:任一条线段延长都能把另一条线段的两端点分开。叉积正负性相反。
多边形面积:随便选一点,叉积。
点在半平面内:叉积。
点到直线距离:叉积。
点在多边形内:引多条射线/三角剖分。
直线夹角:点积。
直线交点:
直线与凸多边形交点:
凸包交:
动态凸包:splay维护。
旋转卡壳:
最小圆覆盖:
随机化的应用:
模拟退火的应用:
离散化的应用:
辛普森积分:
点线对偶:凸包⇔半平面交。(a, b) -> y = ax - b