【模板】闵可夫斯基和以及判断点是否在凸包内
题目链接:https://www.luogu.com.cn/problem/P4557
顺带推一波学姐的博客:https://blog.csdn.net/ying971101/article/details/100110026/
1、两个点集的闵可夫斯基和 的 凸包 == 两个点集的凸包 的 闵可夫斯基 和。
2、求两个凸包的闵可夫斯基和,只需要两个凸包的顺着走的边(就是ai -> ai+1) 都拎出来,极角排序一遍,然后首尾相连即可。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int N = 1e5+9; 8 typedef long long ll; 9 struct Point{ 10 ll x,y; 11 ll cross( Point a, Point b){ 12 return (a.x - x) * (b.y - y) - (b.x - x) * (a.y - y); 13 } 14 ll dot(Point a,Point b){ 15 return (a.x - x)*(b.x - x) + (a.y - y)*(b.y - y); 16 } 17 ll operator ^ (const Point& b)const{ 18 return x * b.y - b.x * y; 19 } 20 ll len()const {return x*x + y*y;} 21 Point operator - (const Point& b)const{ 22 return (Point){ x - b.x,y - b.y}; 23 } 24 Point operator + (const Point& b)const{ 25 return (Point){ x + b.x , y + b.y}; 26 } 27 }pa[N],pb[N],va[N],vb[N],ch[N],pc[N],vc[N]; 28 int na,nb,nc; 29 bool cmp1(const Point& a,const Point& b){ 30 return a.x < b.x || (a.x == b.x && a.y < b.y); 31 } 32 int Andrew(Point* p,int n){ 33 sort(p,p+n,cmp1); 34 int m = 0; 35 for(int i = 0;i<n;++i){ 36 while( m > 1 && ( ch[m-2].cross(p[i],ch[m-1]) >= 0 )) --m; 37 ch[m++] = p[i]; 38 } 39 int k = m; 40 for(int i = n-2;i>=0;--i){ 41 while(m > k && ( ch[m-2].cross(p[i],ch[m-1])) >= 0) --m; 42 ch[m++] = p[i]; 43 } 44 if(n>1) --m; 45 for(int i = 0;i<m;++i) p[i] = ch[i]; 46 return m; 47 } 48 int Minkowski(Point* pa,int na,Point* pb,int nb,Point* pc){ 49 for(int i = 0;i < na-1; ++i) va[i] = pa[i+1] - pa[i]; 50 va[na-1] = pa[0] - pa[na-1]; 51 for(int i = 0;i < nb-1; ++i) vb[i] = pb[i+1] - pb[i]; 52 vb[nb-1] = pb[0] - pb[nb-1]; 53 54 int cnt = 0; 55 pc[cnt++] = pa[0] + pb[0]; 56 int p1 = 0,p2 = 0; 57 while(p1 < na && p2 < nb){ 58 pc[cnt] = pc[cnt - 1] + ( (va[p1] ^ vb[p2]) >= 0 ? va[p1++] : vb[p2++]) ; 59 ++cnt; 60 } 61 while(p1 < na){ 62 pc[cnt] = pc[cnt-1] + va[p1++]; 63 ++cnt; 64 } 65 while(p2 < nb){ 66 pc[cnt] = pc[cnt-1] + vb[p2++]; 67 ++cnt; 68 } 69 return cnt; 70 } 71 Point st; 72 bool cmp2(const Point& a,const Point& b){ 73 return st.cross(a,b) > 0 || (st.cross(a,b) == 0 && (a-st).len() < (b-st).len()); 74 } 75 bool in_cov(Point a,Point* p,int n){ 76 77 if( st.cross(p[1],a) < 0 || st.cross(a,p[n-1]) < 0 ) return 0; 78 int pos = upper_bound(p,p+n,a,cmp2) - p - 1; 79 80 if(p[pos].cross(a,p[(pos+1)%n]) < 0) return 1; 81 if(p[pos].cross(a,p[(pos+1)%n]) == 0) return p[pos].dot(a,p[(pos+1)%n])>=0 ? 1 : 0; 82 return 0; 83 } 84 int main(){ 85 int q; 86 scanf("%d %d %d",&na,&nb,&q); 87 for(int i = 0;i<na;++i) scanf("%lld %lld",&pa[i].x,&pa[i].y); 88 for(int i = 0;i<nb;++i) scanf("%lld %lld",&pb[i].x,&pb[i].y); 89 for(int i = 0;i<nb;++i) pb[i].x = - pb[i].x , pb[i].y = -pb[i].y; 90 na = Andrew(pa,na); 91 nb = Andrew(pb,nb); 92 nc = Minkowski(pa,na,pb,nb,pc); 93 nc = Andrew(pc,nc); 94 Point que; 95 st = pc[0]; 96 for(int i = 1;i<=q;++i){ 97 scanf("%lld %lld",&que.x,&que.y); 98 printf("%d\n",in_cov(que,pc,nc)?1:0); 99 } 100 return 0; 101 }