洛谷P3508LAT-Lamp的题解

题目描述

有两个建筑物,分别有 $n$ 和 $m$ 个窗户,你需要判断一个光源是否照到第一个建筑物的任何一个窗户,如果光线照到了,那么就反射到第二个建筑物,再判断这个光线是否照到了第二个建筑物的任何一个窗户。如果照到了,输出窗户号,并输出照射到的窗户数。

思路

对于这种照射问题,我们可以把它视为连线问题。从光源出发,递归反射,直到反射不到为止。因为两个建筑物都是平行的,所以我们可以把两个轴都作为平面来处理,建立平面直角坐标系。因为这个光源位置不在任何一个窗户的边界上,所以这个坐标系相对固定。

我们可以选择两种方式来计算两点间的连线是否与窗户相交,一种是扫描线算法,另一种是向量法,这里我们使用后者。

对于两个点 $(x_1, y_1), (x_2, y_2)$,可以定义它们的向量为 $\vec{v} = (x_2 - x_1, y_2 - y_1)$,假设光线与窗户分别相交于 $(a, b), (c, d)$,因为法线与反射线上任何一点的向量都相同,所以有 $\vec{v}\cdot\vec{n} = 0$,其中 $\vec{n}$ 为法线向量,其方向在 $(-v_2, v_1)$ 上。因为 $n_1$ 和 $n_2$ 均为 $\pm1$ 并且 $|n_1| + |n_2| = 1$,所以 $n_1$ 和 $n_2$ 中必定有一个为 $0$。因为 $\vec{v}$ 的坐标为整数,所以可以先对两个坐标进行差分,最后再把两个坐标乘上正负号即可,即

$$n_1 = \mathrm{sgn}(v_2),\quad n_2 = -\mathrm{sgn}(v_1)$$

然后,因为上面的法线只是粗略的法线,我们还要对它进行细化,做法是求出两个点的单位向量,然后与粗略法线向量相加,再除法线长度,即

$$\vec{u}_1 = \frac{1}{\sqrt{v_1^2 + v_2^2}}(v_1, v_2),\quad \vec{u}_2 = \frac{1}{\sqrt{v_1^2 + v_2^2}}(-v_2, v_1)$$

$$\vec{n} = (\vec{u}_1 + \vec{u}_2)/\sqrt{2}$$

然后,对于每个窗户,判断从光源到两个窗户的向量与粗略法线的向量积是否同号,如果不同,说明这个光线没有经过这扇窗户,否则递归调用反射函数即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值