题目链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4481
题目大意:
平面上有 n 个点, 每个点为白点或黑点。现在需要放置一条隔板,使得隔板一侧的黑色点数加上另一侧白色点数的和最大。
解题过程:
这是人生第一道 AC 的计算几何题!
由于之前一直没接触过这种题,紫书上的分析也看不懂,一言不合就让我极角排序、叉乘,根本没学过啊QAQ。
然后翻了很多博客,重学了一下极坐标,可算是弄明白了。
题目分析:
首先这题最简单的想法是枚举所有可能的挡板,这样需要枚举两个点,然后统计两端的点。枚举是 n×n, 统计也是 n,总共时间复杂度是 n^3。显然是超时的。
然后扫描法的思想是,按照一定顺序枚举,这样可以动态的维护一个量,省去了扫描时的 n。
所以这题正解是枚举每一个点当作基点,然后计算每个点相对于基点的极角,进行极角排序。然后按极角的大小进行旋转时的枚举。每旋转一次可以根据之前统计的点的个数进行动态的更新(这就是“维护”)。
这题有个可以优化的地方,如果一个点是黑点的话,可以把他映射到关于基点对称的地方去,视为白点。这样扫描的时候只需要统计白点就够了。然后扫描的时候只从扫描 180 度即可。
判断是否超过 180 度用叉乘,a×b = |a| * |b| * sin<a,b>
,两个点叉乘用坐标计算是,x1*y2 - y1*x2
因为向量的模一定是正的,所以只要判断这个叉乘正负,就可以判断 sin 的正负了,即是否超过 180 度。
AC代码:
1 |
|