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

相关推荐
gopher95112 分钟前
go语言Map详解
开发语言·golang
Python私教5 分钟前
Go语言现代web开发15 Mutex 互斥锁
开发语言·前端·golang
小电玩22 分钟前
JAVA SE8
java·开发语言
努力的布布41 分钟前
Spring源码-从源码层面讲解声明式事务的运行流程
java·spring
程序员大金1 小时前
基于SpringBoot的旅游管理系统
java·vue.js·spring boot·后端·mysql·spring·旅游
小丁爱养花1 小时前
记忆化搜索专题——算法简介&力扣实战应用
java·开发语言·算法·leetcode·深度优先
大汉堡~1 小时前
代理模式-动态代理
java·代理模式
爱上语文1 小时前
Springboot三层架构
java·开发语言·spring boot·spring·架构
Crossoads1 小时前
【数据结构】排序算法---快速排序
c语言·开发语言·数据结构·算法·排序算法
6230_1 小时前
git使用“保姆级”教程2——初始化及工作机制解释
开发语言·前端·笔记·git·html·学习方法·改行学it