CCF-CSP 202309-2 坐标变换(其二)

CCF-CSP 202309-2 坐标变换(其二)

  • 题目要求
    • ‍⬛输入格式
    • ‍⬛输出格式
    • ‍⬛样例输入
    • ‍⬛样例输出
    • ‍⬛样例说明
    • ‍⬛评测用例规模与约定
    • ‍⬛评分方式
    • ‍⬛提示
  • 问题解决
    • 80分代码(含逐行代码解释)
      • C++
      • Python
    • 场景拓展

题目要求

对于平面直角坐标系上的坐标 ( x , y ) (x,y) (x,y),小 P 定义了如下两种操作:

  1. 拉伸 k k k 倍:横坐标 x x x 变为 k x kx kx,纵坐标 y y y 变为 k y ky ky
  2. 旋转 θ \theta θ:将坐标 ( x , y ) (x,y) (x,y) 绕坐标原点 ( 0 , 0 ) (0,0) (0,0) 逆时针旋转 θ \theta θ 弧度 ( 0 ≤ θ < 2 π ) (0 \leq \theta < 2\pi) (0θ<2π)。易知旋转后的横坐标为 x c o s θ − y s i n θ xcos\theta-ysin\theta xcosθysinθ,纵坐标为 x s i n θ + y c o s θ xsin\theta+ycos\theta xsinθ+ycosθ

设定好了包含 n n n 个操作的序列 ( t 1 , t 2 , ⋅ ⋅ ⋅ t n ) (t_1,t_2,···t_n) (t1,t2,⋅⋅⋅tn) 后,小 P 又定义了如下查询:

  • i j x y i \quad j \quad x \quad y ijxy:坐标 ( x , y ) (x,y) (x,y) 经过操作 t i , ⋅ ⋅ ⋅ , t j ( 1 ≤ i ≤ j ≤ n ) t_i,···,t_j(1 \leq i \leq j \leq n) ti,⋅⋅⋅,tj(1ijn) 后的新坐标。

对于给定的操作序列,试计算 m m m 个查询的结果。

‍⬛输入格式

从标准输入读入数据。
输入共 n + m + 1 n+m+1 n+m+1 行。
输入的第一行包含空格分隔的两个正整数 n n n m m m,分别表示操作和初始坐标个数。
接下来 n n n 行依次输入 n n n 个操作,每行包含空格分隔的一个整数(操作类型)和一个实数 ( k k k θ \theta θ),形如 1 k 1 \quad k 1k(表示拉伸 k k k 倍)或 2 θ 2 \quad \theta 2θ(表示旋转 θ \theta θ)。
接下来 m m m 行依次输入 m m m 个查询,每行包含空格分隔的四个整数 i i i j j j x x x y y y,含义如前文所述。

‍⬛输出格式

输出到标准输出中。
输出共 m m m 行,每行包含空格分隔的两个实数,表示对应查询的结果。

‍⬛样例输入

10 5
2 0.59
2 4.956
1 0.997
1 1.364
1 1.242
1 0.82
2 2.824
1 0.716
2 0.178
2 4.094
1 6 -953188 -946637
1 9 969538 848081
4 7 -114758 522223
1 9 -535079 601597
8 8 159430 -511187

‍⬛样例输出

-1858706.758 -83259.993
-1261428.46 201113.678
-75099.123 -738950.159
-119179.897 -789457.532
114151.88 -366009.892

‍⬛样例说明

第五个查询仅对输入坐标使用了操作八:拉伸 0.716 0.716 0.716 倍。
横坐标: 159430 × 0.716 = 114151.88 159430×0.716=114151.88 159430×0.716=114151.88
纵坐标: − 511187 × 0.716 = − 366009.892 -511187×0.716=-366009.892 511187×0.716=366009.892
由于具体计算方式不同,程序输出结果可能与真实值有微小差异,样例输出仅保留了三位小数。

‍⬛评测用例规模与约定

80% 的测试数据满足: n , m ≤ 1000 n,m \leq 1000 n,m1000
全部的测试数据满足:

  • n , m ≤ 100000 n,m \leq 100000 n,m100000
  • 输入的坐标均为整数且绝对值不超过 1000000 1000000 1000000
  • 单个拉伸操作的系数 k ∈ [ 0.5 , 2 ] k \in [0.5,2] k[0.5,2]
  • 任意操作区间 t i , ⋅ ⋅ ⋅ , t j ( 1 ≤ i ≤ j ≤ n ) t_i,···,t_j(1 \leq i \leq j \leq n) ti,⋅⋅⋅,tj(1ijn) 内拉伸系数 k k k 的乘积在 [ 0.001 , 1000 ] [0.001,1000] [0.001,1000] 范围内。

‍⬛评分方式

如果你输出的浮点数与参考结果相比,满足绝对误差不大于 0.1 0.1 0.1,则该测试点满分,否则不得分。

‍⬛提示

  • C/C++:建议使用 double 类型存储浮点数,并使用 scanf("%lf", &x); 进行输入,printf("%f", x); 输出,也可以使用 cincout 输入输出浮点数;#include 后可使用三角函数 cos()sin()
  • Python:直接使用 print(x) 即可输出浮点数 x;from math import cos, sin 后可使用相应三角函数。
  • Java:建议使用 double 类型存储浮点数,可以使用 System.out.print(x); 进行输出;可使用 Math.cos()Math.sin() 调用三角函数。

问题解决

80分代码(含逐行代码解释)

因为尝试不使用STL库,所以进行了两层循环导致时间复杂度变高从而运行超时只有80分,若使用STL库则可轻易达到满分,网上可以查到很多满分解答。

C++

#include
using namespace std;

struct operation{
	//定义操作结构体 
	int type; //操作种类k或θ 
	double value; //对应的数值 
}op[1000001];

struct coordinate{
	//定义坐标结构体
	int i; //操作起始
	int j; //操作终止
	double x; //横坐标 
	double y; //纵坐标 
}coor[1000001];

int main(){
	int n, m;
	cin >> n >> m; //输入操作和查询个数
	for(int t = 1; t <= n; t++)
	{
		cin >> op[t].type >> op[t].value; //输入操作编号以及对应的数值k或者θ 
	}
	for(int t = 1; t <= m; t++){
		cin >> coor[t].i >> coor[t].j >> coor[t].x >> coor[t].y; //输入操作范围以及坐标 
	}
	double xx, yy; //用来存储横纵坐标的中间变量,注意是双精度类型 
	for(int t = 1; t <= m; t++){ //大循环表示遍历m个坐标
		for(int p = coor[t].i; p <= coor[t].j; p++){ //小循环表示对每个坐标进行p个变换操作 
			if(op[p].type == 1){ //1对应的是k,直接乘积即可 
				xx = coor[t].x * op[p].value;
				yy = coor[t].y * op[p].value;
			}
			else if(op[p].type == 2){ //2对应的是θ,采用题目中的公式 
				xx = coor[t].x * cos(op[p].value) - coor[t].y * sin(op[p].value);
				yy = coor[t].x * sin(op[p].value) + coor[t].y * cos(op[p].value);
			}
			coor[t].x = xx; //更新横坐标变换后的结果 
			coor[t].y = yy; //更新纵坐标变换后的结果
		}
		cout << fixed << setprecision(3) << xx << " " << yy << "\n";
		//等价于 printf("%.3f %.3f\n", coor[t].x, coor[t].y);
	}
}

Python

#代码逻辑与C++完全一样,不再一一赘述
import math

class Operation:
    def __init__(self, type_, value):
        self.type = type_
        self.value = value

class Coordinate:
    def __init__(self, i, j, x, y):
        self.i = i
        self.j = j
        self.x = x
        self.y = y

n, m = map(int, input().split())
op = [None] * (n + 1)
for t in range(1, n + 1):
    type_, value = map(float, input().split())
    op[t] = Operation(int(type_), value)

coor = [None] * (m + 1)
for t in range(1, m + 1):
    i, j, x, y = map(float, input().split())
    coor[t] = Coordinate(int(i), int(j), x, y)

for t in range(1, m + 1):
    for p in range(coor[t].i, coor[t].j + 1):
        if op[p].type == 1:
            xx = coor[t].x * op[p].value
            yy = coor[t].y * op[p].value
        elif op[p].type == 2:
            xx = coor[t].x * math.cos(op[p].value) - coor[t].y * math.sin(op[p].value)
            yy = coor[t].x * math.sin(op[p].value) + coor[t].y * math.cos(op[p].value)
        coor[t].x = xx
        coor[t].y = yy
    print('{:.3f} {:.3f}'.format(xx, yy))

场景拓展

本题是对上一道题的一个进阶和补充,主要目的在于坐标变换,它可以根据给定的操作类型和数值对坐标进行变换。主要应用场景包括但不限于:

  • 图形变换:可以通过修改操作类型和数值来实现平移、旋转、缩放等图形变换操作。
  • 数据分析与可视化:在数据分析和可视化领域,经常需要对数据进行坐标变换,以便更好地理解和展示数据。
  • 物体运动模拟:在物理模拟和游戏开发中,需要对物体进行坐标变换,以模拟物体的运动轨迹和行为。

你可能感兴趣的:(CCF-CSP,算法,c++,python)