CCF 202206-4 光线追踪 python

该博客介绍了光线追踪算法在Python中的实现,包括将反射镜离散化为反射点,光源的移动与反射,以及如何处理不同类型的反射镜。作者通过创建`reflection`和`light`类来组织代码,并利用字典数据结构存储反射点信息。虽然在CCF评测中因运行超时只获得30分,但博客提供了思路和代码供读者参考。
摘要由CSDN通过智能技术生成

CCF 202206-4 光线追踪 python

CCF官网题目
此题因为运行超时得到了30分,仅为没思路的同学提供一些想法,如果有改进建议欢迎评论!

题目分析

  1. 首先将反射镜转换为单独的反射点,去除反射镜的两端点。例如,反射镜(0,0)–(5,5)就可以转换为反射点(1,1),(2,2),(3,3),(4,4)。
    题目中说“平面中有一些激光光源,每个光源位于一个坐标为整数的点上,会向某个水平或竖直的方向发射一定强度的激光。”。由此可知,光线与反射镜相交时一定是位于一个整数点上,所以反射镜就可以进行离散化,这样可以将坐标系内的点提前进行标记是否为反射点,光源移动到达某个整数点只需要判断其是否为反射点,从而进行相应的操作。
  2. 每个光源单独追踪,以时间和光强进行控制,移动后判断是否到达反射点,更改其光向及光强。
    当到达设定时间阈值t或者光强I<1时,输出结果。本文提前将反射点加入字典point_dict,每次光源移动都要判断是否到达反射点。
    反射点根据其所在反射镜的方向可以分为两类,斜率为-1及1。光线与这两种反射镜相交后的方向改变需要分别进行讨论。
    而光源的移动,有上下左右四种情况,所以每个光源需要有一个参数—光向,这样就可以编程自动化了。
  3. 设置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:524.078KBPYTHON运行超时30运行超时82.93MB

觉得不错,记得帮忙点个赞哟!

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ccf202206-2是CCF(中国计算机学会)的2022年6月份的考试中的第2道题目。根据引用,这道题目是关于在大地图上寻找与小地图匹配的次数。大地图的数据范围很大,所以不能用二维数组进行存储整张地图,而是使用了vector<pair<int, int>>来存储大地图上给出的n个1的坐标。同时,小地图也进行了存储。引用是这道题目的一个参考代码,其中包含了读入数据、进行匹配计数的过程。我们可以根据这段代码理解题目的具体要求和实现方式。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [寻宝,大冒险!CSP202206-2](https://blog.csdn.net/m0_57518208/article/details/125336982)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [CCF部分第四题解答](https://download.csdn.net/download/qq_29187357/9697906)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [202206-2 CCF 寻宝!大冒险! (简单模拟 满分题解)](https://blog.csdn.net/qq_51800570/article/details/126673741)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值