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,可能会在性能上稍逊一些。在处理大量数据时,第二种算法更为推荐。

相关推荐
小七rrrrr3 分钟前
动态规划法 - 53. 最大子数组和
java·算法·动态规划
自由的疯11 分钟前
在 Java IDEA 中使用 DeepSeek 详解
java·后端·架构
自由的疯18 分钟前
Java 通过接口方式使用 DeepSeek 详解
java·后端·trae
敲代码中26 分钟前
Maven入门到精通
java·maven
常利兵27 分钟前
Kotlin作用域函数全解:run/with/apply/let/also与this/it的魔法对决
android·开发语言·kotlin
幼稚园的山代王40 分钟前
Kotlin-基础语法练习一
android·开发语言·kotlin
拂晓银砾1 小时前
Java数据结构-队列
java·数据结构
重生成为编程大王1 小时前
Java ConcurrentHashMap 深度解析
java·开发语言
阿华的代码王国1 小时前
【Android】适配器与外部事件的交互
android·xml·java·前端·后端·交互