by F. Yang
PKU1031题意描述:在坐标原点处有一个点光源S. 在距离S为r处的亮度为
,
其中为与光源有关的常数. 而光对在某处一高度为长度为的小量竖直矩形的照度为
,
其中为该小量矩形处的亮度,为光源到处的方向与的法线方向的夹角.
现有一高度为 的简单多边形篱笆,用点列描述. 原点不在多边形的边上. 求光源对多边形各处的照度的总和.
分析: 设的两端点为A, B. 且A, B在光源S到直线AB的垂足的同侧, 否则只需要将AB从垂足处分为两条线段讨论即可. 另外假设A离垂足较近. 设S到AB的垂线与SA的夹角为, 而S到AB的小量张角为. SA的长度为. 由小量分析的方法可得
.
易知即为上述的. 故得到在处的照度为
.
显然,照度与距离无关,只与张角有关. 故这个问题变成求一个点对一个简单多边形的张角.
求点对多边形张角的问题可以用投影和区间并的思想解决:
(1) 令;
(2 )维护一个闭区间序列ints[], 初始为空;
(3) 对每条条线段, , 求出向量和的辐角, , 设. 若, 则将区间加入到序列ints[]中, 否则分别将区间, 加入到序列ints[]中.
(4) 将区间序列ints[]按左端排序, 合并各个相交的区间;
(5) 最后剩下的不相交区间的长度总和就是所求夹角.
下面为解决这个问题的代码, 函数接口为double angfun(pt p[], int n) , 由于本题光源刚好在原点,所以不当作参数, 对其他点也是容易处理的, 坐标平移一下即可.
讨论: 假设允许点在多边形上, 这个方法也是可用的, 不过我们需要知道这个时候点是看作影响多边形外还是影响多边形内. 另外还需要判断每条边的左侧是内部还是右侧是内部. 这只要按叉积求一次面积即可判断. 具体在此从略. 本部分感谢bigheadghost提示.
PS: PKU上该题做成多case会wrong到死, 要做成单case才能过, 晕死!