| |
|
福州一中 林渌
这一题从算法上来说,使比较简单的,只要仔细看清题目的要求,编程细心且耐心,就不难解决问题。
首先,求凸包是整个问题的基础,因为题目没有给出哪些柱子是在外,哪些在内,而这将是解决问题必须的条件。求凸包可以用卷包裹法或Graham,我想大家对这应该是很熟悉的了。
我们得到凸包之后,很明显可以看出来,第一小题就是求凸包的重心。由于房顶的密度厚度均匀,所以房顶的厚度就是一个不需要考虑的多余条件。求凸多边形重心的一个简单方法就是我们顺次把凸包分割成为n-3个三角心,根据三角形中心的计算公式
就可以得到每个三角形的重心。然后计算三角形面积(如用公式
其中 )。这样我们就可以计算两个图形的重心
,如已知他们的面积(正比于质量)S1,S2,有
,再利用定比分点公式
求出这两个图形整体的重心(x,y)。
这我们可以用很简洁的程序求得:
x:=0; y:=0; s:=0;
for I:=2 to n-1 do
begin
x0:=(dian[1].x+dian[I].x+dian[I+1].x)/3;
y0:=(dian[1].y+dian[I].y+dian[I+1].y)/3;
k:=gets/s; {gets为求当前三角形的面积}
x:=(x+k*x0)/(1+k);
y;=(y+k*y0)/(1+k);
inc(s,gets);
end;
求得的(x,y)即为凸多边形的重心。
当然,大家还可以思考一下如果不一定是凸多边形的情况。
第二个问题,因为物体是竖直落下,我们实际上要判断的就是物体的射影这个点是在圆内、线上、凸多边形内或者凸多边形外?
i) 判断一个点是否在圆内,可以通过计算这个点到圆心的距离,如果距离小于半径那么点就在圆内。
这里还要特别注意一点------精度问题
对于这里求距离不应该用开平方sqrt ,而应将半径平方,否则会导致精度降低无法求得正确答案
ii) 判断一个点是否在线上,可通过下面的方法求得

iii) 判断一个点是否在多边形内,只要从这个点向多边形外做一条射线(随机取极远处的一个点,以这两点为端点做一条线段即可),如果射线不经过多边形顶点,不和多边形边重合(随机取点出现这种情况的概率极小,可以不予考虑,或者发现问题马上重新取点),那么统计射线和多边形的边的交点个数,如果是交点是奇数个表明点在多边形内,否则在多边形外。
当然对于本题还有另外一种较为简洁的方法:将点与重心连一条线判断这条线是否与凸包的边相交.若相交,则在凸边形外;否则,就在凸多边形内
按照上述条件依次判断,也就可以满足本小题CLIO的输出顺序。
第三个问题,要判断一个点是否能够被照射到。我们应该看到,麦克风是没有大小的,而且它和灯都是放在地面上,所以皇宫的高度也是一个无用的条件,我们只要考虑平面问题。如果一个点可以防治麦克风,也就是说,它不能够被任何光线照射到,那么这个点和任何灯的连线都会被某一个柱子所遮挡。也就是说,如果一个点和一个光源的连线不被任何柱子遮挡,这个点才是可见的。一盏灯发出去的光线有无数条,根据物理学易知,我们只要考虑灯和麦克风连线上的这一条光线在灯和麦克风之间的线段就可以了。大致算法是我们依次考虑每个麦克风,看它和每根外柱的连线会不会被某根柱子遮挡。这样算法的时间复杂度为
。关键就是如何判断线段和圆相交,其实有多种可行的方法。标程使用了的方法是计算出线段所在直线和圆的交点,判断焦点是否在线段上。这种方法简单易懂容易想到,只要利用解析几何知识认真笔算一下直线和圆的交点就行了。我的方法是判断圆心到直线的距离及交点,如果相交的话再判断线段的两个端点是否分列在圆心到直线的垂线的两侧。其他方法还有很多,这里就不再介绍了。
至此这样整道题目就解决了,当然计算几何的很多基本算法都可以有不同的实现方法。这道题没有复杂的思想,主要是套用常见的计算几何算法。
参考程序










|
|
|