判断线段与线段相交、射线与线段相交。我在做题的过程中用了二分猜答案再验证的方法。

原题地址:http://poj.org/problem?id=3347

POJ 3347 Kadj 正方形

题目描述

第一象限中有若干个正方形,这些正方形都是斜着摆放的(如图)。正方形下方与 x 轴刚好相交,其横坐标为 b1, b2, …, bi. 其中 b1 的值是这样取的:当第 1 个正方形的左边端点刚好在 y 轴上时,此时该正方形下面的端点与 x 轴相交,横坐标即为 b1. 接下来的 bi 的值应该取得尽量小,并且让该正方形与之前的任何正方形没有相交,并且 bi > bi-1.

题目的要求是找出那些能够从上方竖直往下看,能够被看到的正方形,不管是能完全被看到还是部分被看到。当然这个“看”指的不是透视图的看,而是一个“直线摄像机”的那种感觉……或者可以这样想,在相当高的一个地方,一个点竖直落下之后能够砸到某个正方形(砸到一个正方形之后这个点不会弹开,而是消失掉,以免砸到其它正方形),那么这个正方形就是可以被看到的。

图中 S1, S2, S4 就是能被看到的。

解题思路

首先需要知道数列 b1, b2, …, bi 的值,这个好取,直接按照定义按部就班地来。然后在所有正方形排列好之后,判断每个正方形是否会被看到。

下面谈谈具体的操作。由于给的是正方形的边长,而且还是整数,而且正方形都是 45° 旋转之后摆放的,为了方便,我们可以将边长乘以根号二,这样每个端点的坐标就都是整数了。事实上,为了方便讨论,我们还要把边长乘以二,这样能方便我们判断正方形是否能被看到。

也就是说,输入的正方形边长被我们乘以了 [latex]2 \sqrt{2}[/latex] . 这个根号二好理解,而为什么是两倍的根号二呢……

因为我判断一个正方形是否能被看到的时候,先一一枚举 x 值,再枚举一个横坐标为当前 x 的一个相当高的点 P, 然后枚举一个在 P 点竖直下方的点 Q, 且 Q 高于 x 轴,作线段 PQ, 如果线段 PQ 只与一个正方形相交(无论是规范还是非规范相交),那么可以判断这个正方形是能被看到的;如果不与任何正方形相交或者与多个正方形相交的话,就二分枚举 Q 点再判断相交。

以这种方式判断相交,如果正方形边长不乘以二,并且遇到如图情况,就会判断出错;而如果乘以二,这些情况都能解决。(并不一定只有这两种特殊情况。)

POJ 3347 某种特殊情况①

POJ 3347 某种特殊情况①

POJ 3347 某种特殊情况②

POJ 3347 某种特殊情况②

源代码

原创文章,转载请注明来源:http://euyuil.com/2441/poj-3347-kadj-squares/