acm-计算几何模板
北京大学ACM暑期课讲义-计算几何教程

计算几何教程
计算几何的恶心之处
代码长,难写。
需要讨论各种边界情况。后面所介绍的算
法,有些对于边界情况的处理很完美,不 需要再做讨论;有些则不然,需要自行处 理边界情况。
精度误差
二维矢量
2-Dimension Vector
矢量
既有大小又有方向的量。
算法演示
2 被弹出栈,3 进栈。
算法演示
没有点被弹出栈,4 进栈。
算法演示
4 被弹出栈,5 进栈。
算法演示
5 被弹出栈,6 进栈。
算法演示
6 被弹出栈,7 进栈。
算法演示
如此直到下凸壳被找到。
算法演示
倒序进行扫描找到上凸壳。
Graham 扫描的时间复杂度
这太傻缺了。算法的瓶颈在排序,所以时
总时间复杂度 O(N2 log N)。
算法扩展
SPOJ CIRUT
求恰好被覆盖 1 次、2 次、„、N 次的面积。
算法的本质在于对“裸露”部分进行处理。
这种方法也可以用于求很多圆与很多凸多 边形的面积并——但是情况复杂得多,要 讨论的情况也多得多。
三维矢量
3-Dimension Vector
总体来说讨论比较辛苦,写起来不算很难。
精度存在比较大的问题,而且半平面交的
题目一般都容许 O(N2) 算法,所以并不是 很常用。
半平面交练习题
POJ 1279 POJ 3525 POJ 2451 POJ 3384
求多边形的核。核中的点满足其到多边形边 界上任一点之间的线段只与多边形在那一点相交。 求凸多边形最大内切圆半径。 裸的半平面交。朱泽园专门为他的算法出的 题,要求 O(N log N) 算法。 求在凸多边形内部放两个半径为 r 的圆所能 覆盖的最大面积。两圆可以重叠,但不能与多边形相交。 需要用到旋转卡壳。
acm 计算几何

1.扇形的重心Xc = 2*R*sinA/3/A (A为圆心角的一半)2.N点中三个点组成三角形面积最大#include <stdio.h>#include <stdlib.h>#include <math.h>#define MaxNode 50005int stack[MaxNode];int top;double max;typedef struct TPoint{int x;int y;}TPoint;TPoint point[MaxNode];void swap(TPoint point[], int i, int j){TPoint tmp;tmp = point[i];point[i] = point[j];point[j] = tmp;}double multi(TPoint p1, TPoint p2, TPoint p0){return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); }double distance(TPoint p1, TPoint p2){return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);}int cmp(const void *a, const void *b){TPoint *c = (TPoint *)a;TPoint *d = (TPoint *)b;double k = multi(*c, *d, point[0]);if(k< 0) return 1;else if(k == 0 && distance(*c, point[0]) >= distance(*d, point[0])) return 1;else return -1;}void grahamScan(int n){//Graham扫描求凸包int i, u;//将最左下的点调整到p[0]的位置u = 0;for(i = 1;i <= n - 1;i++){if((point[i].y < point[u].y) ||(point[i].y == point[u].y && point[i].x < point[u].x)) u = i;}swap(point, 0, u);//将平p[1]到p[n - 1]按按极角排序,可采用快速排序qsort(point + 1, n - 1, sizeof(point[0]), cmp);for(i = 0;i <= 2;i++) stack[i] = i;top = 2;for(i = 3;i <= n - 1;i++){while(multi(point[i], point[stack[top]], point[stack[top - 1]]) >= 0){ top--;if(top == 0) break;}top++;stack[top] = i;}}int main(){double triangleArea(int i, int j, int k);void PloygonTriangle();int i, n;while(scanf("%d", &n) && n != -1){for(i = 0;i < n;i++)scanf("%d%d", &point[i].x, &point[i].y);if(n <= 2){printf("0.00\n");continue;}if(n == 3){printf("%.2lf\n", triangleArea(0, 1, 2));continue;}grahamScan(n);PloygonTriangle();printf("%.2lf\n", max);}return 0;}void PloygonTriangle(){double triangleArea(int i, int j, int k);int i, j , k;double area, area1;max = -1;for(i = 0;i <= top - 2;i++){k = -1;for(j = i + 1; j <= top - 1;j++){if(k <= j) k= j + 1;area = triangleArea(stack[i], stack[j], stack[k]);if(area > max) max = area;while(k + 1 <= top){area1= triangleArea(stack[i], stack[j], stack[k + 1]);if(area1 < area) break;if(area1 > max) max = area1;area = area1;k++;}}}}double triangleArea(int i, int j, int k){//已知三角形三个顶点的坐标,求三角形的面积double l = fabs(point[i].x * point[j].y + point[j].x * point[k].y + point[k].x * point[i].y - point[j].x * point[i].y- point[k].x * point[j].y - point[i].x * point[k].y) / 2;return l;}3.N个点最多组成多少个正方形#include<stdio.h>#include<stdlib.h>#include<math.h>#define eps 1e-6#define pi acos(-1.0)#define PRIME 9991struct point{int x, y;}p[2201];int n;struct HASH{int cnt;int next;}hash[50000];int hashl;int Hash(int n){int i = n % PRIME;while(hash[i].next != -1){if(hash[hash[i].next].cnt == n) return 1;else if(hash[hash[i].next].cnt > n) break;i = hash[i].next;}hash[hashl].cnt = n;hash[hashl].next = hash[i].next;hash[i].next = hashl;hashl++;return 0;}int Hash2(int n){int i = n % PRIME;while(hash[i].next != -1){if(hash[hash[i].next].cnt == n) return 1;else if(hash[hash[i].next].cnt > n) return 0;i = hash[i].next;}return 0;}int check(double ax, double ay, int &x, int &y){int a0 = (int)ax;int b0 = (int)ay;int tag1 = 0, tag2 = 0;if(fabs(a0 - ax) < eps){tag1 = 1;x = a0;}else if(fabs(a0 + 1 - ax) < eps){tag1 = 1;x = a0 + 1;}if(fabs(b0 - ay) < eps){tag2 = 1;y = b0;}else if(fabs(b0 + 1 - ay) < eps){y = b0 + 1;tag2 = 1;}if(tag1 == 1 && tag2 == 1) return 1;else return 0;}int squares(point p1, point p2, point &p3, point &p4) {double a = (double)p2.x - p1.x;double b = (double)p2.y - p1.y;double midx = ((double)p1.x + p2.x) / 2;double midy = ((double)p1.y + p2.y) / 2;double tmp = a * a + b * b;double x1 = sqrt(b * b) / 2;double y1;if(fabs(b) < eps) y1 = sqrt(a * a + b * b) / 2;else y1 = -a * x1 / b;x1 += midx;y1 += midy;if(check(x1, y1, p3.x, p3.y) == 0) return 0;x1 = 2 * midx - x1;y1 = 2 * midy - y1;if(check(x1, y1, p4.x, p4.y) == 0) return 0;return 1;}int main(){int i, j, cnt;while(scanf("%d", &n) != EOF && n){for(i = 0;i < PRIME;i++) hash[i].next = -1;hashl = PRIME;int x1, y1, x2, y2;for (i = 0; i < n; i++){scanf("%d%d", &p[i].x, &p[i].y);Hash((p[i].x + 100000) * 100000 + p[i].y + 100000);}cnt = 0;for (i = 0; i < n; i++){for (j = i + 1; j < n; j++){point a, b;if(squares(p[i], p[j], a, b) == 0) continue;if(Hash2((a.x + 100000) * 100000 + a.y + 100000) == 0) continue;if(Hash2((b.x + 100000) * 100000 + b.y + 100000) == 0) continue;cnt++;}}printf("%d\n", cnt / 2);}return 0;}4.单位圆覆盖最多点/*平面上N个点,用一个半径R的圆去覆盖,最多能覆盖多少个点?比较经典的题目。
ACM程序竞赛计算几何超全模板

/*计算几何目录㈠点的基本运算1. 平面上两点之间距离12. 判断两点是否重合13. 矢量叉乘14. 矢量点乘25. 判断点是否在线段上26. 求一点饶某点旋转后的坐标27. 求矢量夹角2㈡线段及直线的基本运算1. 点与线段的关系32. 求点到线段所在直线垂线的垂足43. 点到线段的最近点44. 点到线段所在直线的距离45. 点到折线集的最近距离46. 判断圆是否在多边形内57. 求矢量夹角余弦58. 求线段之间的夹角59. 判断线段是否相交610.判断线段是否相交但不交在端点处611.求线段所在直线的方程612.求直线的斜率713.求直线的倾斜角714.求点关于某直线的对称点715.判断两条直线是否相交及求直线交点716.判断线段是否相交,如果相交返回交点7㈢多边形常用算法模块1. 判断多边形是否简单多边形82. 检查多边形顶点的凸凹性93. 判断多边形是否凸多边形94. 求多边形面积95. 判断多边形顶点的排列方向,方法一106. 判断多边形顶点的排列方向,方法二107. 射线法判断点是否在多边形内108. 判断点是否在凸多边形内119. 寻找点集的graham算法1210.寻找点集凸包的卷包裹法1311.判断线段是否在多边形内1412.求简单多边形的重心1513.求凸多边形的重心1714.求肯定在给定多边形内的一个点1715.求从多边形外一点出发到该多边形的切线1816.判断多边形的核是否存在19㈣圆的基本运算1 .点是否在圆内202 .求不共线的三点所确定的圆21㈤矩形的基本运算1.已知矩形三点坐标,求第4点坐标22㈥常用算法的描述22㈦补充1.两圆关系:242.判断圆是否在矩形内:243.点到平面的距离:254.点是否在直线同侧:255.镜面反射线:256.矩形包含:267.两圆交点:278.两圆公共面积:289. 圆和直线关系:2910. 内切圆:3011. 求切点:3112. 线段的左右旋:3113.公式:32*//* 需要包含的头文件*/#include <cmath >/* 常用的常量定义*/const double INF = 1E200const double EP = 1E-10const int MAXV = 300const double PI = 3.14159265/* 基本几何结构*/struct POINT{double x;double y;POINT(double a=0, double b=0) { x=a; y=b;} //constructor};struct LINESEG{POINT s;POINT e;LINESEG(POINT a, POINT b) { s=a; e=b;}LINESEG() { }};struct LINE // 直线的解析方程a*x+b*y+c=0 为统一表示,约定a >= 0{double a;double b;double c;LINE(double d1=1, double d2=-1, double d3=0) {a=d1; b=d2; c=d3;}};/*********************** ** 点的基本运算** ***********************/double dist(POINT p1,POINT p2) // 返回两点之间欧氏距离{return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) );}bool equal_point(POINT p1,POINT p2) // 判断两个点是否重合{return ( (abs(p1.x-p2.x)<EP)&&(abs(p1.y-p2.y)<EP) );}/****************************************************************************** r=multiply(sp,ep,op),得到(sp-op)和(ep-op)的叉积r>0:ep在矢量opsp的逆时针方向;r=0:opspep三点共线;r<0:ep在矢量opsp的顺时针方向******************************************************************************* /double multiply(POINT sp,POINT ep,POINT op){return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));}/*r=dotmultiply(p1,p2,op),得到矢量(p1-op)和(p2-op)的点积,如果两个矢量都非零矢量r<0:两矢量夹角为锐角;r=0:两矢量夹角为直角;r>0:两矢量夹角为钝角******************************************************************************* /double dotmultiply(POINT p1,POINT p2,POINT p0){return ((p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y));}/****************************************************************************** 判断点p是否在线段l上条件:(p在线段l所在的直线上) && (点p在以线段l为对角线的矩形内)******************************************************************************* /bool online(LINESEG l,POINT p){return( (multiply(l.e,p,l.s)==0) &&( ( (p.x-l.s.x)*(p.x-l.e.x)<=0 )&&( (p.y-l.s.y)*(p.y-l.e.y)<=0 ) ) ); }// 返回点p以点o为圆心逆时针旋转alpha(单位:弧度)后所在的位置POINT rotate(POINT o,double alpha,POINT p){POINT tp;p.x-=o.x;p.y-=o.y;tp.x=p.x*cos(alpha)-p.y*sin(alpha)+o.x;tp.y=p.y*cos(alpha)+p.x*sin(alpha)+o.y;return tp;}/* 返回顶角在o点,起始边为os,终止边为oe的夹角(单位:弧度)角度小于pi,返回正值角度大于pi,返回负值可以用于求线段之间的夹角原理:r = dotmultiply(s,e,o) / (dist(o,s)*dist(o,e))r'= multiply(s,e,o)r >= 1 angle = 0;r <= -1 angle = -PI-1<r<1 && r'>0 angle = arccos(r)-1<r<1 && r'<=0 angle = -arccos(r)*/double angle(POINT o,POINT s,POINT e){double cosfi,fi,norm;double dsx = s.x - o.x;double dsy = s.y - o.y;double dex = e.x - o.x;double dey = e.y - o.y;cosfi=dsx*dex+dsy*dey;norm=(dsx*dsx+dsy*dsy)*(dex*dex+dey*dey);cosfi /= sqrt( norm );if (cosfi >= 1.0 ) return 0;if (cosfi <= -1.0 ) return -3.1415926;fi=acos(cosfi);if (dsx*dey-dsy*dex>0) return fi; // 说明矢量os 在矢量oe的顺时针方向return -fi;}/*****************************\* ** 线段及直线的基本运算** *\*****************************//* 判断点与线段的关系,用途很广泛本函数是根据下面的公式写的,P是点C到线段AB所在直线的垂足AC dot ABr = ---------||AB||^2(Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)= -------------------------------L^2r has the following meaning:r=0 P = Ar=1 P = Br<0 P is on the backward extension of ABr>1 P is on the forward extension of AB0<r<1 P is interior to AB*/double relation(POINT p,LINESEG l){LINESEG tl;tl.s=l.s;tl.e=p;return dotmultiply(tl.e,l.e,l.s)/(dist(l.s,l.e)*dist(l.s,l.e));}// 求点C到线段AB所在直线的垂足PPOINT perpendicular(POINT p,LINESEG l){double r=relation(p,l);POINT tp;tp.x=l.s.x+r*(l.e.x-l.s.x);tp.y=l.s.y+r*(l.e.y-l.s.y);return tp;}/* 求点p到线段l的最短距离,并返回线段上距该点最近的点np注意:np是线段l上到点p最近的点,不一定是垂足*/double ptolinesegdist(POINT p,LINESEG l,POINT &np){double r=relation(p,l);if(r<0){np=l.s;return dist(p,l.s);}if(r>1){np=l.e;return dist(p,l.e);}np=perpendicular(p,l);return dist(p,np);}// 求点p到线段l所在直线的距离,请注意本函数与上个函数的区别double ptoldist(POINT p,LINESEG l){return abs(multiply(p,l.e,l.s))/dist(l.s,l.e);}/* 计算点到折线集的最近距离,并返回最近点.注意:调用的是ptolineseg()函数*/double ptopointset(int vcount,POINT pointset[],POINT p,POINT &q) {int i;double cd=double(INF),td;LINESEG l;POINT tq,cq;for(i=0;i<vcount-1;i++)l.s=pointset[i];l.e=pointset[i+1];td=ptolinesegdist(p,l,tq);if(td<cd){cd=td;cq=tq;}}q=cq;return cd;}/* 判断圆是否在多边形内.ptolineseg()函数的应用2 */bool CircleInsidePolygon(int vcount,POINT center,double radius,POINT polygon[]){POINT q;double d;q.x=0;q.y=0;d=ptopointset(vcount,polygon,center,q);if(d<radius||fabs(d-radius)<EP)return true;elsereturn false;}/* 返回两个矢量l1和l2的夹角的余弦(-1 --- 1)注意:如果想从余弦求夹角的话,注意反余弦函数的定义域是从0到pi */double cosine(LINESEG l1,LINESEG l2){return (((l1.e.x-l1.s.x)*(l2.e.x-l2.s.x) +(l1.e.y-l1.s.y)*(l2.e.y-l2.s.y))/(dist(l1.e,l1.s)*dist(l2.e,l2.s))) );}// 返回线段l1与l2之间的夹角单位:弧度范围(-pi,pi)double lsangle(LINESEG l1,LINESEG l2){POINT o,s,e;o.x=o.y=0;s.x=l1.e.x-l1.s.x;s.y=l1.e.y-l1.s.y;e.x=l2.e.x-l2.s.x;e.y=l2.e.y-l2.s.y;return angle(o,s,e);// 如果线段u和v相交(包括相交在端点处)时,返回true////判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) ×( Q2 - Q1 ) * ( Q2 - Q1 ) ×( P2 - Q1 ) >= 0。
ACM_10[1].计算几何
![ACM_10[1].计算几何](https://img.taocdn.com/s3/m/364d2ebcd0f34693daef5ef7ba0d4a7302766ce8.png)
ACM_10[1].计算⼏何Computational GeometryComputational GeometryPrerequisitesGraph TheoryShortest PathToolsThis module discusses several algorithms that calculate various geometric properties,mostly based on only two operations described below: cross product and arctangent.Cross ProductThe cross product of u and v is written as u x v. Computationally, the cross product of twothree?dimensional vectors u and v is the vector determinant of the following matrix (where i, j, and k are unit vectors in the x, y, and z directions respectively):| i j k || ux uy uz || vx vy vz |That equation works out to:(u y v z?u z v y)i + (u z v x?u x v z)j + (u x v y?u y v x)k1Dot productThe dot product of two vectors u and v is a scalar written as u * v. Computationally, it is defined in three dimensions as: u x v x + u y v y + u z v zThe dot product is actually equal to the product of:the length of uthe length of vthe cosine of the angle between u and v.Presuming u and v are non?zero, if the dot product if negative, u and v make an angle greater than 90 degrees. If it is zero, then u and v are perpendicular. If u cdot v is positive, then the two vectors form an acute angle.ArctangentThe arctangent function calculates the (an) angle whose tangent is its argument and generally returns a real number between ?pi/2 and pi/2. An additional function in C, atan2, takes two arguments: a DELTA y value and a DELTA x value (in that order!). It determines the angle between the given vector and the positive x axis and returns a value between ?pi and pi.This has the advantage of removing concerns about dividing by zero or writing code to repair angles in order to handle the negative x cases. The atan2 function is almost always easier to use than the simpler atan function that takes only one argument.Particular Debugging ProblemsThe main problem with geometric problems is that they spawn a lot of special cases. Be on the lookout for these special cases and make sure your program works for all of them.Floating point calculations also create a new set of problems. Floating point calculations are rarely precise, as the computer only maintains so many bits (digits) of accuracy: be aware of this. In particular, when checking if two values are equal, check to see if they are within some small tolerance of each other not precisely equal.Geometric AlgorithmsHere are some of snippets that can help you solve geometry problems.Area of TriangleTo calculate the area of a triangle with vertices (a, b, c), pick a vertex (say a) and create a vector to the other two vertices (let u = b ? a, and v = c ? a). The area of the triangle (a, b, c) is one half the length of cross product u x v.Computational GeometryAn alternative method to find the area of triangle is to use Hero's formula. If the lengths of the sides of a triangle are a, b, and c, let s = (a+b+c)/2. The area of the triangle is thensqrt(s* (s?a)*(s?b)*(s?c)) .Are Two Line Segments Parallel?To check if two line segments are parallel, create vectors along each line segment and check to see if their cross product is (almost) zero.Area of polygonThe area of a polygon with vertices (x 1, y 1), ..., (x n, y n) is equal to the determinant:1 | x1 x2 ... xn || |2 | y1 y2 ... yn |where the determinate is defined to be similar to the 2 by 2 determinant: x1 y2 + x2y3 + ... +x n y1 ? y1 x2 ? y2x3 ? ... ? y n x1Distance from a point to a lineThe distance from a point P to a line AB is given by the magnitude of the cross product. In particular, d(P,AB) = |(P ? A) x (B ?A)| / | B ? A| .To determine the distance from a point P to the plane defined by A, B, and C, let n = (B ? A) x (C ? A). The distance is then give by the following equation: d(P,ABC) = (P?A) * n / |n|. Points on a lineA point is on a line if the distance from the point to the line is 0.Points on the same side of lineThis notion only makes sense for two dimensions. To check if points C and D are on the same side of line AB, calculate the z component of (B ? A) x (C ? A) and (B ? A) x (D ? A). If the z components have the same sign (i.e., their product is positive), then C and D are on the same side of the line AB.Point on line segmentTo calculate if a point C is on the line segment AB, check if C is on the line AB. If it is, then check if the length of AB is equal to the sum of the lengths of AC and CB.Point in triangleTo check if a point A is in a triangle, find another point B which is within the triangle (the average of the three vertices works well). Then, check if the point A is on the same side of the three lines defined by the edges of the triangle as B.3Computational GeometryGraph ProblemsSometimes what may look like a geometric problem is really a graph problem. Just because the input is points in the plane does not mean it's a geometric algorithm.Example ProblemsPoint MovingGiven a set of line segments in the plane, and two points A and B, is it possible to move from A to B without crossing any of the segments?The line segments partition the plane into regions. Determine these regions, and see if A and B reside in the same region. Bicycle RoutingGiven a collection of non?intersecting buildings along with start and end locations, find the shortest path from A to B that doesn't go through any buildings.Analysis: This is really a graph problem. The nodes are the start and end locations, along with the vertices of the buildings. There are edges between any two nodes such that the line segment between them does not intersect any buildings, with weight equal to the length of the length of the line segments. Once that graph has been calculated, the problem is shortest path.Maximizing Line IntersectionsGiven a collection of segments in the plane, find the greatest number of segments which can by intersected by drawing a single line.Analysis: With a little bit of thought, it is clear that the line segment must pass through twoof the vertices of the collection of line segments. Thus, try all pairs of vertices, and calculate the crossing for each. Combining this with partitioning gives an algorithm that runs fairly quickly.Polygon ClassificationGiven a collection of segments defining a polygon, determine if it is simple (no twonon?consecutive line segments intersect) and convex.7。
ACM计算几何模板__HIT_jerrybond.

ACM@HIT
Au分 1.几何公式.............................................................................................................................................. 5 1.1 三角形 ....................................................................................................................................... 5 1.2 四边形 ....................................................................................................................................... 5 1.3 正 n 边形 ...................................................................................................................................5 1.4 圆............................................................................................................................................... 5 1.5 棱柱.........................................
ACM常用算法模板

专用模板目录:一、图论1.最大团2.拓扑排序3.最短路和次短路4.SAP模板5.已知各点度,问能否组成一个简单图6.KRUSKAL7. Prim算法求最小生成树8. Dijkstra9 . Bellman-ford10. SPFA11. Kosaraju 模板12. tarjan 模板二、数学1. 剩余定理2. N!中质因子P的个数3.拓展欧几里得4.三角形的各中心到顶点的距离和5.三角形外接圆半径周长6.归并排序求逆序数7. 求N!的位数8.欧拉函数9. Miller-Rabin,大整数分解,求欧拉函数10. 第一类斯特林数11.计算表达式12.约瑟夫问题13.高斯消元法14. Baby-step,giant-step n是素数.n任意15. a^b%c=a ^(b%eular(c)+eular(c)) % c16.判断第二类斯特林数的奇偶性17.求组合数C(n,r)18.进制转换19.Ronberg算法计算积分20.行列式计算21. 返回x 的二进制表示中从低到高的第i位22.高精度运算 +-*/23.超级素数筛选三、数据结构1.树状数组2.线段树求区间的最大、小值3.线段树求区间和4.单调队列5.KMP模板6. 划分树,求区间第k小数7.最大堆,最小堆模板8. RMQ模板求区间最大、最小值9.快速排序,归并排序求逆序数.10.拓展KMP四、计算几何1.凸包面积2.Pick公式求三角形内部有多少点3.多边形边上内部各多少点以及面积pick4.平面最远点对5.判断矩形是否在矩形内6.判断点是否在多边形内7.判断4个点(三维)是否共面8.凸包周长9.等周定理变形一直两端点和周长求最大面积10.平面最近点对11.单位圆最多覆盖多少点(包括边上)12.多边形费马点求点到多边形各个点的最短距离13.矩形并周长14.zoj 2500 求两球体积并一、图论1.最大团#include<iostream>#include<algorithm>using namespace std;int n,m;int cn;//当前顶点数int best;//当前最大顶点数int vis[50];//当前解int bestn[50];//最优解int map[50][50];//临界表void dfs(int i){if(i>n){for(int j=1;j<=n;j++) bestn[j]=vis[j];best=cn;return ;}int ok=1;for(int j=1;j<i;j++){if(vis[j]==1&&map[i][j]==0){ok=0;break;}}if(ok){//进入左子树vis[i]=1;cn++;dfs(i+1);cn--;}if(cn+n-i>best){//进入右子树vis[i]=0;dfs(i+1);}}int main(){while(scanf("%d%d",&n,&m)==2){memset(vis,0,sizeof(vis));memset(map,0,sizeof(map));while(m--){int p,q;scanf("%d%d",&p,&q);map[p][q]=map[q][p]=1;//无向图}cn=0;best=0;dfs(1);printf("%d\n",best);}return 0;}2.拓扑排序#include<iostream>#include<cstring>using namespace std;int map[105][105],in[105],vis[105],ans[105],n;int flag;void dfs(int step){if(flag) return ;if(step==n+1) {flag=1; printf("%d",ans[1]);for(int i=2;i<=n;i++) printf(" %d",ans[i]);printf("\n");return ;}for(int i=1;i<=n;i++){if(vis[i]==0&&in[i]==0){vis[i]=1;for(int j=1;j<=n;j++){if(map[i][j]>0){map[i][j]=-map[i][j];in[j]--;}}ans[step]=i;dfs(step+1);vis[i]=0;for(int j=1;j<=n;j++){if(map[i][j]<0){map[i][j]=-map[i][j];in[j]++;}}}}}int main(){while(scanf("%d",&n)==1){flag=0;memset(map,0,sizeof(map));memset(vis,0,sizeof(vis));memset(in,0,sizeof(in));for(int i=1;i<=n;i++){int t;while(scanf("%d",&t),t){map[i][t]=1;in[t]++;}}dfs(1);}return 0;}3.最短路和次短路#include<iostream>#include<cstdio>#include<vector>#include<cstring>using namespace std;class Node{public:int e,w;//表示终点和边权};const int inf=(1<<25);int main(){int ci;cin>>ci;while(ci--){vector<Node> G[1005];//用邻接表存边int n,m;cin>>n>>m;for(int i=1;i<=m;i++){Node q;int u;cin>>u>>q.e>>q.w;G[u].push_back(q);}int s,f;//起点和终点cin>>s>>f;//dijkstra 求最短路和次短路int flag[1005][2];int dis[1005][2],cnt[1005][2];//0表示最短路,1表示次短路memset(flag,0,sizeof(flag));for(int i=1;i<=n;i++) dis[i][0]=dis[i][1]=inf;dis[s][0]=0;cnt[s][0]=1;//初始化for(int c=0;c<2*n;c++) //找最短路和次短路,故要进行2*n次循环也可以改成while(1){int temp=inf,u=-1,k;//找s-S'集合中的最短路径,u记录点的序号,k记录是最短路或者是次短路for(int j=1;j<=n;j++){if(flag[j][0]==0&&temp>dis[j][0]) temp=dis[j][0],u=j,k=0;else if(flag[j][1]==0&&temp>dis[j][1]) temp=dis[j][1],u=j,k=1;}if(temp==inf) break;//S'集合为空或者不联通,算法结束//更新路径flag[u][k]=1;for(int l=0;l<G[u].size();l++){int d=dis[u][k]+G[u][l].w,j=G[u][l].e;//important//4种情况if(d<dis[j][0]){dis[j][1]=dis[j][0];cnt[j][1]=cnt[j][0];dis[j][0]=d;cnt[j][0]=cnt[u][k];}else if(d==dis[j][0]){cnt[j][0]+=cnt[u][k];}else if(d<dis[j][1]){dis[j][1]=d;cnt[j][1]=cnt[u][k];}else if(d==dis[j][1]){cnt[j][1]+=cnt[u][k];}}}int num=cnt[f][0];//最短路int cc=cnt[f][1];//次短路}return 0;}4.SAP模板#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int inf=(1<<31)-1;const int point_num=300;int cap[point_num][point_num],dist[point_num],gap[point_num];//初始化见main里面int s0,t0,n;//源,汇和点数int find_path(int p,int limit=0x3f3f3f3f){if(p==t0) return limit;for(int i=0;i<n;i++)if(dist[p]==dist[i]+1 && cap[p][i]>0){int t=find_path(i,min(cap[p][i],limit));if(t<0) return t;if(t>0){cap[p][i]-=t;cap[i][p]+=t;return t;}}int label=n;for(int i=0;i<n;i++) if(cap[p][i]>0) label=min(label,dist[i]+1);if(--gap[dist[p]]==0 || dist[s0]>=n ) return -1;++gap[dist[p]=label];return 0;}int sap(){//初始化s,ts0=0,t0=n-1;int t=0,maxflow=0;gap[0]=n;while((t=find_path(s0))>=0) maxflow+=t;return maxflow;}int main(){int ci;while(cin>>ci>>n){//初始化memset(cap,0,sizeof(cap));memset(dist,0,sizeof(dist));memset(gap,0,sizeof(gap));//初始化capwhile(ci--){int x,y,c;cin>>x>>y>>c;x--;y--;cap[x][y]+=c;//因题而异}int ans=sap();cout<<ans<<endl;}return 0;}5.已知各点度,问能否组成一个简单图#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int inf=(1<<30);int d[1100];bool cmp(int x,int y){return x>y;}int main(){int ci;scanf("%d",&ci);while(ci--){int n,flag=1,cnt=0;scanf("%d",&n); for(int i=0;i<n;i++){scanf("%d",&d[i]);if(d[i]>n-1||d[i]<=0) flag=0; cnt+=d[i];}if(flag==0||cnt%2){printf("no\n");continue;}sort(d,d+n,cmp);for(int l=n;l>0;l--){for(int i=1;i<l&&d[0];i++){d[0]--,d[i]--;if(d[i]<0){flag=0;break;}}if(d[0]) flag=0;if(flag==0) break;d[0]=-inf;sort(d,d+l,cmp);}if(flag) printf("yes\n");else printf("no\n");}return 0;}6.KRUSKAL#include<iostream>#include<algorithm>using namespace std;int u[15005],v[15005],w[15005],fath[15005],r[15005];int ans1[15005],ans2[15005];bool cmp(int i,int j){return w[i]<w[j];}int find(int x){return fath[x]==x?x:fath[x]=find(fath[x]);}int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++) fath[i]=i;for(int i=1;i<=m;i++) r[i]=i;for(int i=1;i<=m;i++){cin>>u[i]>>v[i]>>w[i];}sort(r+1,r+m+1,cmp);int maxn=0,ans=0,k=0;for(int i=1;i<=m;i++){int e=r[i];int x=find(u[e]),y=find(v[e]);if(x!=y){ans+=w[e];fath[x]=y;if(w[e]>maxn) maxn=w[e];ans1[k]=u[e];ans2[k++]=v[e];}}return 0;}7.prime求最小生成树语法:prim(Graph G,int vcount,int father[]);参数:G:图,用邻接矩阵表示vcount:表示图的顶点个数father[]:用来记录每个节点的父节点返回值:null注意:常数max_vertexes 为图最大节点数常数infinity为无穷大源程序:#define infinity 1000000#define max_vertexes 5typedef int Graph[max_vertexes][max_vertexes];void prim(Graph G,int vcount,int father[]){int i,j,k;intlowcost[max_vertexes],closeset[max_vertexes],used[max_vertexes]; for (i=0;i<vcount;i++){lowcost[i]=G[0][i];closeset[i]=0;used[i]=0;father[i]=-1;}used[0]=1;for (i=1;i<vcount;i++){j=0;while (used[j]) j++;for (k=0;k<vcount;k++)if ((!used[k])&&(lowcost[k]<lowcost[j])) j=k;father[j]=closeset[j];used[j]=1;for (k=0;k<vcount;k++)if (!used[k]&&(G[j][k]<lowcost[k])){ lowcost[k]=G[j][k];closeset[k]=j; }}}8.Dijkstra语法:result=Dijkstra(Graph G,int n,int s,int t, int path[]); 参数:G:图,用邻接矩阵表示n:图的顶点个数s:开始节点t:目标节点path[]:用于返回由开始节点到目标节点的路径返回值:最短路径长度注意:输入的图的权必须非负顶点标号从0 开始用如下方法打印路径:i=t;while (i!=s){printf("%d<--",i+1);i=path[i];}printf("%d\n",s+1);源程序:int Dijkstra(Graph G,int n,int s,int t, int path[]){int i,j,w,minc,d[max_vertexes],mark[max_vertexes];for (i=0;i<n;i++) mark[i]=0;for (i=0;i<n;i++){ d[i]=G[s][i];path[i]=s; }mark[s]=1;path[s]=0;d[s]=0;for (i=1;i<n;i++){minc=infinity;w=0;for (j=0;j<n;j++)if ((mark[j]==0)&&(minc>=d[j])) {minc=d[j];w=j;}mark[w]=1;for (j=0;j<n;j++)if((mark[j]==0)&&(G[w][j]!=infinity)&&(d[j]>d[w]+G[w][j])){ d[j]=d[w]+G[w][j];path[j]=w; }}return d[t];}9.Bellman-ford语法:result=Bellman_ford(Graph G,int n,int s,int t,int path[],int success);参数:G:图,用邻接矩阵表示n:图的顶点个数s:开始节点t:目标节点path[]:用于返回由开始节点到目标节点的路径success:函数是否执行成功返回值:最短路径长度注意:输入的图的权可以为负,如果存在一个从源点可达的权为负的回路则success=0顶点标号从0 开始用如下方法打印路径:i=t;while (i!=s){printf("%d<--",i+1);i=path[i];}printf("%d\n",s+1);源程序:int Bellman_ford(Graph G,int n,int s,int t,int path[],int success){int i,j,k,d[max_vertexes];for (i=0;i<n;i++) {d[i]=infinity;path[i]=0;}d[s]=0;for (k=1;k<n;k++)for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]){d[j]=d[i]+G[i][j];path[j]=i;}success=0;for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]) return 0;success=1;return d[t];}10. SPFA#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;const __int64 maxn=1001000;const __int64 inf=1000100000;struct edge//邻接表{__int64 t,w;//s->t=w;__int64 next;//数组模拟指针};__int64 p[maxn],pf[maxn];//邻接表头节点edge G[maxn],Gf[maxn];//邻接表__int64 V,E;//点数[1-n] 边数__int64 dis[maxn];__int64 que[maxn],fro,rear;//模拟队列__int64 vis[maxn];__int64 inque[maxn];//入队次数bool spfa(__int64 s0){fro=rear=0;for(__int64 i=1;i<=V;i++) dis[i]=inf;dis[s0]=0;memset(vis,0,sizeof(vis));memset(inque,0,sizeof(inque));que[rear++]=s0;vis[s0]=1;inque[s0]++;while(fro!=rear){__int64 u=que[fro];fro++;if(fro==maxn) fro=0;vis[u]=0;for(__int64 i=p[u];i!=-1;i=G[i].next){__int64 s=u,t=G[i].t,w=G[i].w;if(dis[t]>dis[s]+w){dis[t]=dis[s]+w;if(vis[t]==0){que[rear++]=t,vis[t]=1;inque[t]++;if(inque[t]>V) return false;if(rear==maxn) rear=0;}}}}return true;}int main(){__int64 ci;scanf("%I64d",&ci);while(ci--){scanf("%I64d%I64d",&V,&E);memset(p,-1,sizeof(p));memset(pf,-1,sizeof(pf)); for(__int64 i=0;i<E;i++){__int64 u,v,w;scanf("%I64d%I64d%I64d",&u,&v,&w);G[i].t=v;G[i].w=w;G[i].next=p[u];p[u]=i;Gf[i].t=u;Gf[i].w=w;Gf[i].next=pf[v];pf[v]=i;}__int64 ans=0;spfa(1);//求第一个点到其他点的最短距离和for(__int64 i=1;i<=V;i++) ans+=dis[i];//反方向再来一次spfa 求其他点到第一个点的最短距离和 for(__int64 i=1;i<=V;i++) p[i]=pf[i];for(__int64 i=0;i<E;i++) G[i]=Gf[i];spfa(1);for(__int64 i=1;i<=V;i++) ans+=dis[i];printf("%I64d\n",ans);}return 0;}11.Kosaraju模板#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;struct edge{int t,w;//u->t=w;int next;};int V,E;//点数(从1开始),边数int p[maxn],pf[maxn];//邻接表原图,逆图edge G[maxn],Gf[maxn];//邻接表原图,逆图int l,lf;void init(){memset(p,-1,sizeof(p));memset(pf,-1,sizeof(pf));l=lf=0;}void addedge(int u,int t,int w,int l){G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}void addedgef(int u,int t,int w,int lf){Gf[l].w=w;Gf[l].t=t;Gf[l].next=pf[u];pf[u]=l;}///Kosaraju算法,返回为强连通分量个数bool flag[maxn]; //访问标志数组int belg[maxn]; //存储强连通分量,其中belg[i]表示顶点i属于第belg[i]个强连通分量int numb[maxn]; //结束时间(出栈顺序)标记,其中numb[i]表示离开时间为i的顶点//用于第一次深搜,求得numb[1..n]的值void VisitOne(int cur, int &sig){flag[cur] = true;for (int i=p[cur];i!=-1;i=G[i].next){if (!flag[G[i].t]){VisitOne(G[i].t,sig);}}numb[++sig] = cur;}//用于第二次深搜,求得belg[1..n]的值void VisitTwo(int cur, int sig){flag[cur] = true;belg[cur] = sig;for (int i=pf[cur];i!=-1;i=Gf[i].next){if (!flag[Gf[i].t]){VisitTwo(Gf[i].t,sig);}}//Kosaraju算法,返回为强连通分量个数int Kosaraju_StronglyConnectedComponent(){int i, sig;//第一次深搜memset(flag,0,sizeof(flag));for ( sig=0,i=1; i<=V; ++i ){if ( false==flag[i] ){VisitOne(i,sig);}}//第二次深搜memset(flag,0,sizeof(flag));for ( sig=0,i=V; i>0; --i ){if ( false==flag[numb[i]] ){VisitTwo(numb[i],++sig);}}return sig;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int u=i,t,w=1;while(scanf("%d",&t)==1&&t){E++;addedge(u,t,w,l++);addedgef(t,u,w,lf++);}}int ans=Kosaraju_StronglyConnectedComponent(); printf("%d\n",ans);}return 0;12.tarjan模板//自己模板#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;int V,E;//点数(1) 边数struct edge//邻接表{int t,w;//u->t=w;int next;};int p[maxn];//表头节点edge G[maxn];int l;void init(){memset(p,-1,sizeof(p));l=0;}//添加边void addedge(int u,int t,int w,int l)//u->t=w;{G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}//tarjan算法求有向图强联通分量int dfn[maxn],lowc[maxn];//dfn[u]节点u搜索的次序编号,lowc[u]u或者u的子树能够追溯到的栈中的最早的节点int belg[maxn];//第i个节点属于belg[i]个强连通分量int stck[maxn],stop;//stck栈int instck[maxn];//第i个节点是否在栈中int scnt;//强联通分量int index;void dfs(int i){dfn[i]=lowc[i]=++index;instck[i]=1;//节点i入栈stck[++stop]=i;for(int j=p[i];j!=-1;j=G[j].next){int t=G[j].t;//更新lowc数组if(!dfn[t])//t没有遍历过{dfs(t);if(lowc[i]>lowc[t]) lowc[i]=lowc[t];}//t是i的祖先节点else if(instck[t]&&lowc[i]>dfn[t]) lowc[i]=dfn[t];}//是强连通分量的根节点if(dfn[i]==lowc[i]){scnt++;int t;do{t=stck[stop--];instck[t]=0;belg[t]=scnt;}while(t!=i);}}int tarjan(){stop=scnt=index=0;memset(dfn,0,sizeof(dfn));memset(instck,0,sizeof(instck));for(int i=1;i<=V;i++){if(!dfn[i]) dfs(i);}return scnt;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int x;while(scanf("%d",&x)==1&&x){E++;addedge(i,x,1,l++);}}int ans=tarjan();printf("%d\n",ans);}return 0;}//吉大模板邻接表版#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;int V,E;//点数(1) 边数struct edge//邻接表{int t,w;//u->t=w;int next;};int p[maxn];//表头节点edge G[maxn];int l;void init(){memset(p,-1,sizeof(p));l=0;}//添加边void addedge(int u,int t,int w,int l)//u->t=w;{G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}//tarjan算法求有向图强联通分量int dfn[maxn],lowc[maxn];//dfn[u]节点u搜索的次序编号,lowc[u]u或者u的子树能够追溯到的栈中的最早的节点int stck[maxn],stop;//stck栈int pre[maxn];//int scnt;//强联通分量int cnt;//void dfs(int v)//1-V{int t,minc=lowc[v]=pre[v]=cnt++;stck[stop++]=v;for(int i=p[v];i!=-1;i=G[i].next){int pv=G[i].t;if(pre[pv]==-1) dfs(pv);if(lowc[pv]<minc) minc=lowc[pv]; }if(minc<lowc[v]){lowc[v]=minc;return ;}do{dfn[t=stck[--stop]]=scnt;lowc[t]=V;}while(t!=v);++scnt;}int tarjan(){stop=cnt=scnt=0;memset(pre,-1,sizeof(pre));for(int i=1;i<=V;i++){if(pre[i]==-1) dfs(i);}return scnt;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int x;while(scanf("%d",&x)==1&&x){E++;addedge(i,x,1,l++);}}int ans=tarjan();printf("%d\n",ans);}return 0;}二、数学1.剩余定理int mod(int c[],int b[],int n){int all_multy=1,sum=0;int i,j,x[5];for(i=0;i<n;i++)all_multy*=c[i];for(i=0;i<n;i++)x[i]=all_multy/c[i];for(i=0;i<n;i++){j=1;while((x[i]*j)%c[i]!=1)j++;x[i]*=j;}for(i=0;i<n;i++)sum+=(b[i]*x[i]);return sum%all_multy;}2.N!中质因子P的个数//对于任意质数p,n!中有(n/p+n/p^2+n/p^3+...)个质因子p。
ACM常用模板代码

{
k=s[i]*m+add;
if (k>=10)
{
s[i]=k%10;
add=k/10;
flag=1;
}
else
{
s[i]=k;
flag=0;
add=0;
}
}
if (flag)
{
l=i+1;
s[i]=add;
}
else l=i;
for (i=0; i<l; i++)
{
p=pr[i-1]*pr[1];
q=pi[i-1]*pi[1];
s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);
pr[i]=p-q;
pi[i]=s-p-q;
}
for (it=0; it<=n-2; it=it+2)
{
vr=fr[it];
vi=fi[it];
fr[it]=vr+fr[it+1];
s2[i-j]=c;
}
s2[i+1]='\0';
}
7.最大公约数、最小公倍数
语法:resulet=hcf(int a,int b)、result=lcd(int a,int b)
参数:
a:
int a,求最大公约数或最小公倍数
b:
int b,求最大公约数或最小公倍数
返回值:
返回最大公约数(hcf)或最小公倍数(lcd)
k=k+1;
sum=sum/10;
}
for (i=blen-2;i>=0;i--)
ACM计算几何模板__HIT_jerrybond.

ACd
1
基础部分 1.几何公式.............................................................................................................................................. 5 1.1 三角形 ....................................................................................................................................... 5 1.2 四边形 ....................................................................................................................................... 5 1.3 正 n 边形 ...................................................................................................................................5 1.4 圆............................................................................................................................................... 5 1.5 棱柱.......................................
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<bits/stdc++.h>using namespace std;const double eps =1e-8;const double INF =1e20;const double pi = acos ;int dcmp (double x) {if (fabs (x) < eps) return0;return (x <0-1:1);》}inline double sqr (double x) {return x*x;}f %.2f\n", x, y);}bool operator== (const Point &b) const {return (dcmp ==0&& dcmp ==0);}bool operator< (const Point &b) const {return (dcmp ==0 dcmp <0: x < ;};Point operator+ (const Point &b) const {return Point (x+, y+;}Point operator- (const Point &b) const {return Point , ;}Point operator* (double a) {return Point (x*a, y*a);}Point operator/ (double a) {`return Point (x/a, y/a);}double len2 () {f\n", r);}bool operator== (const Circle &a) const {return p ==&& (dcmp ==0);}double area () {otate_left ());Line v = Line ((b+c)/2, ((b+c)/2) + (c-b).rotate_left ()); Point p = line_intersection (u, v);]double r = dis (p, a);return Circle (p, r);}Circle in_circle (Point a, Point b, Point c) { r -l*l);Point tmp =+ (l);p1 = tmp + ( ().change_len (h));p2 = tmp + ( ().change_len (h));if (rel ==2|| rel ==4) return1;return2;~}int line_cirlce_intersection (Line v, Circle u, Point &p1, Point &p2) {hange_len (r1));= q + ( ().change_len (r1));== r1;return2;}Line u1 = Line + ().change_len (r1), + ().change_len (r1)); Line u2 = Line + ().change_len (r1), + ().change_len (r1)); Circle cc = Circle (q, r1);.Point p1, p2;if (!line_cirlce_intersection (u1, cc, p1, p2))line_cirlce_intersection (u2, cc, p1, p2);c1 = Circle (p1, r1);if (p1 == p2) {c2 = c1;return1;}c2 = Circle (p2, r1);return2;、}int get_circle (Line u, Line v, double r1, Circle &c1, Circle &c2, Circle &c3, Circle &c4) {hange_len (r1), + ().change_len (r1));Line u2 = Line + ().change_len (r1), + ().change_len (r1)); Line v1 = Line + ().change_len (r1), + ().change_len (r1)); Line v2 = Line + ().change_len (r1), + ().change_len (r1));==== r1;= line_intersection (u1, v1);= line_intersection (u1, v2);= line_intersection (u2, v1);#= line_intersection (u2, v2);return4;}int get_circle (Circle cx, Circle cy, double r1, Circle &c1, Circle &c2) {otate_left ());v = u;return1;}double d = dis , q);double l =*d;。
double h = sqrt *- l*l);u = Line (q, + .change_len (l) + .rotate_left ().change_len (h)); v = Line (q, + .change_len (l) + .rotate_right ().change_len (h));return2;}double area_circle (Circle a, Circle v) {" << endl;return res;}-- ;int d2 = dcmp (b[(i+1)%n].y - ;if (k >0&& d1 <=0&& d2 >0)w++;if (k <0&& d2 <=0&& d1 >0)w--;}if (w !=0)return1;return0;·}int convex_cut (Line u, Point *p, int n, Point *po) {//直线切割多边形左侧//返回切割后多边形的数量int top =0;for (int i =0; i < n; i++) {int d1 = dcmp (cross p[i]);int d2 = dcmp (cross p[(i+1)%n]);if (d1 >=0) po[top++] = p[i];if (d1*d2 <0) po[top++] = line_intersection (u, Line (p[i], p[(i+1)%n]));(}return top;}double convex_circumference (Point *p, int n) {//多边形的周长(凹凸都可以)double ans =0;for (int i =0; i < n; i++) {ans += dis (p[i], p[(i+1)%n]);}return ans;@}double area_polygon_circle (Circle c, Point *p, int n) {//多边形和圆交面积double ans =0;for (int i =0; i < n; i++) {int j = (i+1)%n; //cout << i << " " << j << "//" << endl;if (dcmp (cross (p[j], p[i]) >=0)ans += circle_traingle_area (p[i], p[j], c);elseans -= circle_traingle_area (p[i], p[j], c);、}return fabs (ans);}Point centre_of_gravity (Point *p, int n) {//多边形的重心(凹凸都可以) double sum = , sumx =0, sumy =0;Point p1 = p[0], p2 = p[1], p3;for (int i =2; i <= n-1; i++) {p3 = p[i];double area = cross (p2-p1, p3-p2)/;~sum += area;sumx +=++*area;sumy +=++*area;p2 = p3;}return Point (sumx/*sum), sumy/*sum));}int convex_hull (Point *p, Point *ch, int n) {//求凸包//所有的点集凸包点集点集的点数!sort (p, p+n);int m =0;for (int i =0; i < n; i++) {while (m >1&& cross (ch[m-1]-ch[m-2], p[i]-ch[m-1]) <=0) m--;ch[m++] = p[i];}int k = m;for (int i = n-2; i >=0; i--) {while (m > k && cross (ch[m-1]-ch[m-2], p[i]-ch[m-1]) <=0) m--;ch[m++] = p[i];}if (n >1)m--;return m;}。