计算几何

基本操作

判断两线段是否相交

跨立实验,两点是否在异侧,两条线段都成立即相交。

此实现不含端点

bool Cross(node A,node B,node C,node D){
  return ((B-A)*(C-A))*((B-A)*(D-A))<0&&((D-C)*(A-C))*((D-C)*(B-C))<0;
}

判断点是否在直线上

判外积是否为零可知是否共直线,需两点异侧,判内积是否为非正即可。

此实现含端点

bool inedge(node A,node B,node x){
  return (A-x)*(B-x)==0&&((A-x)^(B-x))<=0;
}

判断一点是否在多边形内部

射线法,从该点引一条水平射线,判断此线经过多边形的边次数奇偶性即可。
考虑边界问题,单独处理该点在多边形边上的情况。
经过多边形顶点的情况,只计算在其上方的边的个数。

bool inpolygon(node x){
	int tot=0;
	rpt(i,1,n)if(inedge(i==1?a[n]:a[i-1],a[i],x))return 1;
	rpt(i,1,n)tot+=Cross(i==1?a[n]:a[i-1],a[i],x,{inf,x.y});
	rpt(i,1,n)if(x.y-a[i].y==0&&a[i].x>x.x)tot+=((i==1?a[n].y:a[i-1].y)>x.y)+((i==n?a[1].y:a[i+1].y)>x.y);
	return tot%2;
}

例题

Security at Museums
简要题意
\(n\) 个顶点的平面多边形,集合为凸包的点集计数。

\(sol\)
先预处理出任意两点间线段是否在多边形内。
若中间经过端点则为合并两个线段,记忆化后可做到 \(O(n^3)\)
若中间经过多边形边(不含端点)则为假。
否则判中点是否在多边形内部即可。

然后考虑 \(dp\)
先钦定 \(dp\) 顺序,考虑一个凸包的极角一定是单调的,先按将线段按极角排序。
考虑极角相同的线段的顺序是一定的,将极角相同的线段一起转移。
一条线段中间经过的端点可选可不选,贡献为 \(2^n\)
一个凸包的贡献为所有线段贡献的乘积。
最后减去只有两个点的多余贡献即可。

posted @ 2025-10-09 18:26  C_Wish  阅读(10)  评论(0)    收藏  举报