2024 ccfcsp认证打卡 2023 09 02 坐标变换(其二)

202309-2 坐标变换(其二)


题解1

java 复制代码
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt(); // 操作次数
        int m = scan.nextInt(); // 初始坐标个数

        // 存储操作序列的ArrayList,每个操作为长度为2的double数组
        ArrayList<double[]> op = new ArrayList<>();

        // 初始化所有操作的累积倍数为1
        for (int i = 0; i <= n; i++) {
            op.add(new double[] {1, 0}); // 初始操作是不进行变换,k=1, sita=0
        }

        // 读取每个操作的类型和值,并存储到op中
        for (int i = 1; i <= n; i++) {
            int type = scan.nextInt(); // 操作类型,1表示乘法,2表示加法
            double val = scan.nextDouble(); // 操作值
            if (type == 1) {
                // 如果是乘法操作,更新k值,sita不变
                op.set(i, new double[] {op.get(i - 1)[0] * val, op.get(i - 1)[1]});
            } else {
                // 如果是加法操作,更新sita值,k不变
                op.set(i, new double[] {op.get(i - 1)[0], op.get(i - 1)[1] + val});
            }
        }

        // 对每个初始坐标进行操作并输出结果
        for (int i = 0; i < m; i++) {
            int l = scan.nextInt(); // 左边界
            int r = scan.nextInt(); // 右边界
            double x = scan.nextDouble(); // 初始x坐标
            double y = scan.nextDouble(); // 初始y坐标

            // 计算从l到r的累积旋转角度和累积缩放倍数
            double sum_sita = op.get(r)[1] - op.get(l - 1)[1];
            double sum_k = op.get(r)[0] / op.get(l - 1)[0];

            // 根据公式计算最终的坐标
            double nx = x * Math.cos(sum_sita) - y * Math.sin(sum_sita);
            double ny = x * Math.sin(sum_sita) + y * Math.cos(sum_sita);

            // 输出结果
            System.out.println(nx * sum_k + " " + ny * sum_k);
        }

        scan.close();
    }
}

题解2

java 复制代码
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt(); // 操作次数
        int m = scan.nextInt(); // 初始坐标个数

        // 存储操作序列的ArrayList,每个操作为长度为2的double数组
        ArrayList<double[]> op = new ArrayList<>();

        // 初始化所有操作的累积倍数为1
        for (int i = 0; i <= n; i++) {
            op.add(new double[] {1, 0}); // 初始操作是不进行变换,k=1, sita=0
        }

        // 读取每个操作的类型和值,并存储到op中
        for (int i = 1; i <= n; i++) {
            int type = scan.nextInt(); // 操作类型,1表示乘法,2表示加法
            double val = scan.nextDouble(); // 操作值
            if (type == 1) {
                // 如果是乘法操作,更新k值,sita不变
                op.set(i, new double[] {op.get(i - 1)[0] * val, op.get(i - 1)[1]});
            } else {
                // 如果是加法操作,更新sita值,k不变
                op.set(i, new double[] {op.get(i - 1)[0], op.get(i - 1)[1] + val});
            }
        }

        // 对每个初始坐标进行操作并输出结果
        for (int i = 0; i < m; i++) {
            int l = scan.nextInt(); // 左边界
            int r = scan.nextInt(); // 右边界
            double x = scan.nextDouble(); // 初始x坐标
            double y = scan.nextDouble(); // 初始y坐标

            // 计算从l到r的累积旋转角度和累积缩放倍数
            double sum_sita = op.get(r)[1] - op.get(l - 1)[1];
            double sum_k = op.get(r)[0] / op.get(l - 1)[0];

            // 根据公式计算最终的坐标
            double nx = x * Math.cos(sum_sita) - y * Math.sin(sum_sita);
            double ny = x * Math.sin(sum_sita) + y * Math.cos(sum_sita);

            // 输出结果
            System.out.println(nx * sum_k + " " + ny * sum_k);
        }

        scan.close();
    }
}

区别

第一种算法(使用ArrayList存储操作序列):

数据结构:

使用了ArrayList<double[]>来存储操作序列。

每个操作是一个长度为2的double数组,存储了操作的缩放倍数和旋转角度。

操作序列处理:

在读取每个操作时,将其存储为一个数组,然后放入ArrayList中。

对每个操作序列进行遍历,根据操作类型更新缩放倍数和旋转角度。

每次操作都要通过ArrayList的get和set方法来获取和更新操作,可能需要多次遍历操作序列。

第二种算法(使用两个数组存储累积结果):

数据结构:

使用两个数组double[] k和double[] sita来分别存储累积的缩放倍数和旋转角度。

k数组存储缩放倍数,sita数组存储旋转角度。

操作序列处理:

在读取每个操作时,直接根据操作类型更新对应的数组元素。

操作序列处理时不需要遍历,直接根据索引获取和更新操作。

对比

效率

第一种算法使用ArrayList,操作时需要多次调用get和set方法,可能会造成性能损失,特别是在大量数据时。

第二种算法使用数组,直接根据索引获取和更新操作,更加高效。

简洁性

第一种算法使用了ArrayList,需要定义和操作ArrayList,代码相对复杂一些。

第二种算法直接使用数组,代码结构更简洁。

可读性

两种算法在理解上都是相对清晰的,但对于不熟悉ArrayList的人来说,第二种算法可能更容易理解。

总体来说,第二种算法使用数组直接存储累积结果,更加高效和简洁,而第一种算法使用了ArrayList,可能会在性能上稍逊一些。在处理大量数据时,第二种算法更为推荐。

相关推荐
Legendary_0083 分钟前
解析 PD Sink 与 LDR6500U:Type-C 取电的核心密码
c语言·开发语言
冴羽yayujs9 分钟前
JavaScript 9 个先有库再有 API 的故事
开发语言·javascript·ecmascript
回忆2012初秋11 分钟前
.NET 8.0 实战:基于 MQTTnet 封装高可用的 MQTT 发布/订阅工具类
开发语言·mqtt·.net
油丶酸萝卜别吃27 分钟前
JavaScript 深度合并函数 deepMerge 实现指南(附完整测试用例)
开发语言·javascript·测试用例
念恒1230632 分钟前
Python(for循环进阶)
开发语言·python
YOU OU32 分钟前
SpringBoot 配置文件
java·spring boot·后端
c++之路33 分钟前
观察者模式(Observer Pattern)
java·网络·观察者模式
Dicky-_-zhang35 分钟前
云原生存储与数据库选型实战:从传统数据库到云原生数据库的演进
java·jvm
凝小飞40 分钟前
cucumber JAVA 一键部署指南
java·集成测试·模块测试
java修仙传40 分钟前
Java 实习日记:断面状态筛选 Bug 修复与对比案例日期过滤优化
java·bug·实习