CCF 202206-4 光线追踪 python
CCF官网题目
此题因为运行超时得到了30分,仅为没思路的同学提供一些想法,如果有改进建议欢迎评论!
题目分析
- 首先将反射镜转换为单独的反射点,去除反射镜的两端点。例如,反射镜(0,0)–(5,5)就可以转换为反射点(1,1),(2,2),(3,3),(4,4)。
题目中说“平面中有一些激光光源,每个光源位于一个坐标为整数的点上,会向某个水平或竖直的方向发射一定强度的激光。”。由此可知,光线与反射镜相交时一定是位于一个整数点上,所以反射镜就可以进行离散化,这样可以将坐标系内的点提前进行标记是否为反射点,光源移动到达某个整数点只需要判断其是否为反射点,从而进行相应的操作。 - 每个光源单独追踪,以时间和光强进行控制,移动后判断是否到达反射点,更改其光向及光强。
当到达设定时间阈值t
或者光强I<1
时,输出结果。本文提前将反射点加入字典point_dict
,每次光源移动都要判断是否到达反射点。
反射点根据其所在反射镜的方向可以分为两类,斜率为-1及1。光线与这两种反射镜相交后的方向改变需要分别进行讨论。
而光源的移动,有上下左右四种情况,所以每个光源需要有一个参数—光向,这样就可以编程自动化了。 - 设置
reflection、light
两个类,并灵活使用python的字典数据结构。
代码
class reflection:
def __init__(self, x1, y1, x2, y2, a):
self.x1 = x1
self.x2 = x2
self.y1 = y1
self.y2 = y2
self.a = a
def gradient(self):
return (self.x1 - self.x2) / (self.y1 - self.y2)
def insert_reflection(self):
if self.x1 < self.x2:
j = self.y1
for i in range(self.x1 + 1, self.x2):
if self.gradient() == 1:
j = j + 1
else:
j = j - 1
point_dict[(i, j)] = [self.gradient(), self.a]
else:
j = self.y2
for i in range(self.x2 + 1, self.x1):
if self.gradient() == 1:
j = j + 1
else:
j = j - 1
point_dict[(i, j)] = [self.gradient(), self.a]
def remove_reflection(self):
if self.x1 < self.x2:
j = self.y1
for i in range(self.x1 + 1, self.x2):
if self.gradient() == 1:
j = j + 1
else:
j = j - 1
del point_dict[(i, j)]
else:
j = self.y2
for i in range(self.x2 + 1, self.x1):
if self.gradient() == 1:
j = j + 1
else:
j = j - 1
del point_dict[(i, j)]
class light:
def __init__(self, x, y, d, I, t):
self.x = x
self.y = y
self.d = d
self.I = I
self.t = t
def move(self):
# d 的含义为:d = 0 表示沿 x 坐标增加的方向,d = 1 表示沿 y 坐标增加的方向,d = 2 表示沿 x 坐标减小的方向,d = 3 表示沿 y 坐标减小的方向
if self.d == 0:
self.x = self.x + 1
elif self.d == 1:
self.y = self.y + 1
elif self.d == 2:
self.x = self.x - 1
else:
self.y = self.y - 1
def change_d(self, g):
if g == 1:
if self.d == 0:
self.d = 1
elif self.d == 1:
self.d = 0
elif self.d == 2:
self.d = 3
else:
self.d = 2
elif g == -1:
if self.d == 0:
self.d = 3
elif self.d == 1:
self.d = 2
elif self.d == 2:
self.d = 1
else:
self.d = 0
def time_pass(self):
while self.t > 0 and self.I >= 1:
self.t = self.t - 1
self.move()
# 判断此时的(x,y)是否处于反射点 | 反射点的方向 1 或者 -1 | 修改d
if (self.x, self.y) in point_dict.keys():
reflection = point_dict[(self.x, self.y)]
self.change_d(reflection[0])
self.I = reflection[1] * self.I
if __name__ == "__main__":
# 是否为反射镜
point_dict = {}
reflection_dict = {}
m = int(input())
# 1 x1 y1 x2 y2 a :反射系数为 a 的反射面
# 2 k :删除第 k 个操作插入的反射面
# 3 x y d I t :发射光线的方向为 d ,强度为 I ,求其所经 t 时刻后光线到达的坐标以及采样得到的光线强度
for i in range(m):
input_list = list(input().split())
if int(input_list[0]) == 1:
reflection_dict[i + 1] = reflection(x1=int(input_list[1]), y1=int(input_list[2]), x2=int(input_list[3]),
y2=int(input_list[4]),
a=float(input_list[5]))
reflection_dict[i + 1].insert_reflection()
elif int(input_list[0]) == 2:
reflection_dict[int(input_list[1])].remove_reflection()
else:
light_temp = light(x=int(input_list[1]), y=int(input_list[2]), d=int(input_list[3]), I=float(input_list[4]),
t=int(input_list[5]))
light_temp.time_pass()
if int(light_temp.I) == 0:
print(0, 0, 0)
else:
print(light_temp.x, light_temp.y, int(light_temp.I))
结果
提交编号 | 用户名 | 姓名 | 试题名称 | 提交时间 | 代码长度 | 编程语言 | 评测结果 | 得分 | 时间使用 | 空间使用 |
---|---|---|---|---|---|---|---|---|---|---|
3132778 | 佚名 | 佚名 | 光线追踪 | 08-01 19:52 | 4.078KB | PYTHON | 运行超时 | 30 | 运行超时 | 82.93MB |
觉得不错,记得帮忙点个赞哟!