闵可夫斯基和

这里是有图的讲解

两个点集 A , B A,B A,B 的闵可夫斯基和为 C = { a + b   ∣   a ∈ A , b ∈ B } C=\{a+b~|~a\in A,b\in B\} C={a+b  aA,bB}

两个凸包的闵可夫斯基和是由两个凸包的边平移组成的凸包。

初始点为两个凸包的左下角相加,然后第一个向量由两个凸包中极角小的边组成,依次移动两个凸包的边,比较极角,然后决定哪个先放。

例题:LOJ#2549. 「JSOI2018」战争
讲解在上面博客里有。

Code:

#include
#define maxn 100005
#define LL long long
using namespace std;
int n,m,k,Q;
struct Point{
	int x,y; Point(int x=0,int y=0):x(x),y(y){}
	Point operator + (const Point &p){return Point(x+p.x,y+p.y);}
	Point operator - (const Point &p){return Point(x-p.x,y-p.y);}
	LL operator * (const Point &p){return 1ll*x*p.y-1ll*y*p.x;}
	bool operator < (const Point &p)const{return x==p.x?y<p.y:x<p.x;}
}a[maxn],b[maxn],v1[maxn],v2[maxn],p[maxn];
bool cmpang(Point a,Point b){return a*b>0;}
void Convex(Point *a,int &n){
	static Point q[maxn]; int l,r;
	sort(a+1,a+1+n),q[l=r=1]=a[1];
	for(int i=2;i<=n;q[++r]=a[i],i++) while(l<r&&(q[r]-q[r-1])*(a[i]-q[r-1])<=0) r--;
	l=r; for(int i=n-1;i>=1;q[++r]=a[i],i--) while(l<r&&(q[r]-q[r-1])*(a[i]-q[r-1])<=0) r--;
	n=r; for(int i=1;i<=n;i++) a[i]=q[i];
}
void Minkowski(){
	for(int i=1;i<n;i++) v1[i]=a[i+1]-a[i];
	for(int i=1;i<m;i++) v2[i]=b[i+1]-b[i];
	int l=1,r=1; p[k=1]=a[1]+b[1];
	while(l<n&&r<m) ++k,p[k]=p[k-1]+(v1[l]*v2[r]>=0?v1[l++]:v2[r++]);
	while(l<n) ++k,p[k]=p[k-1]+v1[l++];
	while(r<m) ++k,p[k]=p[k-1]+v2[r++];
}
bool In(Point v){
	int i=lower_bound(p+1,p+k+1,v,cmpang)-p-1;
	return !i||i==k?0:(p[i+1]-p[i])*(v-p[i])>=0;
}
int main()
{
	scanf("%d%d%d",&n,&m,&Q);
	for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
	for(int i=1;i<=m;i++) scanf("%d%d",&b[i].x,&b[i].y),b[i].x=-b[i].x,b[i].y=-b[i].y;
	Convex(a,n),Convex(b,m);
	Minkowski();
	Convex(p,k),k--;
	Point bs=p[1]; for(int i=1;i<=k;i++) p[i]=p[i]-bs;
	for(int x,y;Q--;) scanf("%d%d",&x,&y),puts(In(Point(x,y)-bs)?"1":"0");
}

U p d Upd Upd
M i n k o w s k i Minkowski Minkowski 写法可以更简洁,不用把向量存下来,每次加入的点其实就是 a i + b j a_i+b_j ai+bj,只需要判断 i + + i++ i++ 还是 j + + j++ j++ 就可以了。比如这样:

void Minkowski(){
	int i=1,j=1; P[++Pn]=A[i]+B[j];
	while(i<An||j<Bn) j==Bn||(i<An&&(A[i+1]-A[i])*(B[j+1]-B[j])<=0)?i++:j++, P[++Pn]=A[i]+B[j];
}

你可能感兴趣的:(计算几何)