https://scut.online/p/244
除了常规的求凸包求面积,还有一个判断点在凸包内,先找出点所在的三角扇区。
#include<bits/stdc++.h> using namespace std; #define ll long long /****************************凸包模板*******************************/ const double eps = 1e-6; int sgn(double x) { if(fabs(x) < eps) return 0; if(x < 0) return -1; else return 1; } struct Point { double x,y; Point() {} Point(double _x,double _y) { x = _x; y = _y; } Point operator -(const Point &b)const { return Point(x - b.x,y - b.y); } //叉积 double operator ^(const Point &b)const { return x*b.y - y*b.x; } //点积 double operator *(const Point &b)const { return x*b.x + y*b.y; } void input() { scanf("%lf%lf",&x,&y); } void output() { printf("(%.2f,%.2f) ",x,y); } }; struct Line { Point s,e; Line() {} Line(Point _s,Point _e) { s = _s; e = _e; } }; //*两点间距离 double dist(Point a,Point b) { return sqrt((a-b)*(a-b)); } /* * 求凸包,Graham算法 * 点的编号0~n-1 * 返回凸包结果Stack[0~top-1]为凸包的编号 */ const int MAXN = 100000+5; Point List[MAXN]; int Stack[MAXN];//用来存放凸包的点 int top;//表示凸包中点的个数 //相对于List[0]的极角排序 bool _cmp(Point p1,Point p2) { double tmp = (p1-List[0])^(p2-List[0]); if(sgn(tmp) > 0) return true; else if(sgn(tmp) == 0 && sgn(dist(p1,List[0]) - dist(p2,List[0])) <= 0) return true; else return false; } Point p[MAXN]; void Graham(int n) { Point p0; int k = 0; p0 = List[0]; //找最下边的一个点 for(int i = 1; i < n; i++) { if((p0.y>List[i].y) || (p0.y == List[i].y && p0.x > List[i].x) ) { p0 = List[i]; k = i; } } swap(List[k],List[0]); sort(List+1,List+n,_cmp); if(n == 1) { top = 1; Stack[0] = 0; return; } if(n == 2) { top = 2; Stack[0] = 0; Stack[1] = 1; return ; } Stack[0] = 0; Stack[1] = 1; top = 2; for(int i = 2; i < n; i++) { while(top > 1 && sgn((List[Stack[top-1]]-List[Stack[top-2]])^(List[i]-List[Stack[top-2]])) <= 0) top--; Stack[top++] = i; } for(int i=0;i<top;i++){ p[i]=List[Stack[i]]; } } bool inside(Point A) { int l=1,r=top-2,mid; while(l<=r) { mid=(l+r)>>1; double a1=(p[mid]-p[0])^(A-p[0]); double a2=(p[mid+1]-p[0])^(A-p[0]); if(sgn(a1)>=0&&sgn(a2)<=0) { if(sgn((p[mid+1]-p[mid])^(A-p[mid]))>=0) return true; return false; } else if(a1<0) { r=mid-1; } else { l=mid+1; } } return false; } /****************************凸包模板*******************************/ int main() { int n; while(~scanf("%d",&n)){ double x,y; for(int i=0;i<n;i++) { scanf("%lf%lf",&x,&y); List[i].x=x; List[i].y=y; } Graham(n); /*for(int i=0; i<top; i++) { List[Stack[i]].output(); }*/ double area=0.0; Point o(0,0); for(int i=0; i<top; i++) { area+=(List[Stack[i]]-o)^(List[Stack[(i+top-1)%top]]-o); } area*=0.5; area=fabs(area); printf("%.6f ",area); int m; scanf("%d",&m); while(m--){ double x,y; scanf("%lf%lf",&x,&y); if(inside(Point(x,y))){ printf("Yes "); } else{ printf("No "); } } } }