又来到了十分弱势的计算几何上,手中对付几何题的武器又多了一把
本人对牛书上那个N^2算法不感冒,便直接学习这个高级点的算法(集训队朱泽园论文)
略读一遍,英文太多十分之碍眼,加之论文讲的又不太清楚,所以一度陷入迷惘
磨蹭了良久,无意中翻见一标程,竟然就是一个简单的双端队列,豁然开朗,遂速切出此模板
好了,结束废话,进入正题
算法思想非常简单,把直线按极角排序之后,在顺序扫描的过程中求出可行域,整个过程有点类似于凸包那个扫描法
实现的时候,除了一个存当前可行域上的直线的双端队列之外,我还弄了个点队列,记相邻两直线的交点
每次加入i号结点时,看上一个交点有没有在i号直线的可行域内,如果没有,就退掉上一条直线,一直这样做(大家可以自己心里想一下这个过程)
而如果只退队尾,就可能判不出第一条直线是不是有用的了,所以还要类似地退队首
需要注意的是,共线的情况是要分题目特殊处理的,有的取<e,有的却要<-e,看允不允许共线;还有扫描完了之后,最后还得用队首直线去退一下队尾
还有一个小地方,我发现网上大多数选手写极角排序都是先算极角再做,这样不仅精度而且不太漂亮(我认为。。个人意见,仅供参考),我这里用的是象限第一关键字,叉积再判来排的序,这个“象限”还可以简化一点,两个就够了,因为在pi内,叉积是能判出左右来的
代码(模板):
很多时候,网上几百行的恐怖代码都是纸老虎,自己编才发现。。并不难!
学完了知识,搞几道题,就简略地总结一下吧:
pku2451
纯裸。。。
pku3525
求凸多边形内最大圆
二分将凸多边形“内缩”mid,半平面交判断是否存在可行域
这里贴出内缩的那段代码吧,其他的差不多
啊,这里其实还是编丑了,我用相似三角形算的。。。
pku3384
题意是用两个给定半径的圆覆盖一个多边形,问最多能覆盖多边形的面积
这题就每条直线内缩R,求个最远点对就可以了
代码差不多,就不贴了
p.s discuss里说spj很诡异,但可能我比较走运吧,ms没出什么精度啊,输出顺序之类的乱七八糟错误!HAPPY
pku1755
这是我所做的几道题里面最巧妙的一道了,参考了一下discuss里的某神牛做法
首先把让i号人获胜转化为n-1个不等式组是很显然的,但三个参量一般的线性规划做不了,怎么办?
记a,b,c为三段的长度,s=a+b+c,先同除s,又(a+b+c)/s=1,所以可以消掉c,就可以用半平面交的算法了!
需要注意的是,记得要添加3条直线,a>0,b>0,a+b<1
无聊,贴个代码
还是计算几何害死人,虽说每个程序都沿用模板,但基本上每道题都要调蛮久,功夫还是不够深啊,做几何题也算是一种历练吧!
好像有个很nb的单纯型算法也可以做,有空再去研究