凸多边形面积并 复杂度O(N^2 * logN) (N为总边数)
今天突然有人问我有关凸多边形面积并的算法,由于马上要去北京比赛了,就匆匆写个大概的算法流程。其中有很多细节和需要证明的地方都略过了(建议还是主要看代码吧),如果有什么不清楚或错误的地方还请指出。
首先,先向AC大牛致敬,他的凸多边形面积并的算法给我帮助很大,让我学到了很多东西。
AC大牛的博文:http://hi.baidu.com/aekdycoin/blog/item/fbe5a03232c71952ad4b5fcc.html
这里凸多边形面积并的算法非本人原创,是参考Codeforces Round #83 DIV1 的 E题syntax_error的代码而学习到的。
题目链接:http://codeforces.com/contest/107/problem/E
代码链接:http://codeforces.com/contest/107/status/E
syntax_error的算法思想类似于梯形剖分。
主要想法就是把多边形的上下边界进行梯形剖分求面积,然后相减得到所求区域的面积
预处理:将所有的凸多边形的点按照逆时针排列,并去除退化为线段或点的“凸多边形”。
将所有凸多边形的有向边分为三类:向左、向右和垂直于x轴的。对应于下图中的蓝色边、红色边和黄色边。(黄色的边无视)
对于蓝色的边(计算面积的过程如下图)
对于红色的边(计算面积的过程如下图)
其实蓝色的边和红色的边的处理方法都是一样的,只要计算边“暴露在外”的部分到x轴的面积。
蓝色部分和红色部分面积相减后,可以发现两个凸多边形面积并的部分恰好计算了一次,而其他部分蓝色覆盖层数和红色覆盖层数相同(即下图中黑色边框部分)。
其中的原因我就不细说了,大家可以自己体会一下。
处理出每条边所在直线,并去重(这里用方程y = k x + b 的k和b来表示一条直线,方便去重和后续处理)。
对于每条直线,需要求出它和每个多边形的交点,该直线和某多边形恰有两个交点时(其他情况不做处理),把两个交点对应x轴坐标处分别标上0和1;0表示进入某多边形内,1表示从多边形中出来。
另外还要记录这条直线上被多边形的边覆盖的区域有哪些,与上面类似的,分别标记2和3;2表示进入某线段,3表示从线段中出来。
然后将标记过的坐标点排序,从小到大遍历,并且维护两个变量in、ct(in表示在几个多边形内,ct表示被几条多边形的边覆盖)。当in == 0且ct > 0时需要统计该梯形面积