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

相关推荐
Source.Liu6 分钟前
【用Rust写CAD】第二章 第四节 函数
开发语言·rust
monkey_meng6 分钟前
【Rust中的迭代器】
开发语言·后端·rust
余衫马9 分钟前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng13 分钟前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
七星静香14 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员15 分钟前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU15 分钟前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie619 分钟前
在IDEA中使用Git
java·git
小白学大数据22 分钟前
正则表达式在Kotlin中的应用:提取图片链接
开发语言·python·selenium·正则表达式·kotlin
VBA633723 分钟前
VBA之Word应用第三章第三节:打开文档,并将文档分配给变量
开发语言