对于平面直角坐标系上的坐标 ( x , y ) (x,y) (x,y),小 P 定义了如下两种操作:
设定好了包含 n n n 个操作的序列 ( t 1 , t 2 , ⋅ ⋅ ⋅ t n ) (t_1,t_2,···t_n) (t1,t2,⋅⋅⋅tn) 后,小 P 又定义了如下查询:
对于给定的操作序列,试计算 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,m≤1000
全部的测试数据满足:
如果你输出的浮点数与参考结果相比,满足绝对误差不大于 0.1 0.1 0.1,则该测试点满分,否则不得分。
scanf("%lf", &x);
进行输入,printf("%f", x);
输出,也可以使用 cin
和 cout
输入输出浮点数;#include
后可使用三角函数 cos()
和 sin()
。print(x)
即可输出浮点数 x;from math import cos, sin
后可使用相应三角函数。System.out.print(x);
进行输出;可使用 Math.cos()
和 Math.sin()
调用三角函数。因为尝试不使用STL库,所以进行了两层循环导致时间复杂度变高从而运行超时只有80分,若使用STL库则可轻易达到满分,网上可以查到很多满分解答。
#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);
}
}
#代码逻辑与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))
本题是对上一道题的一个进阶和补充,主要目的在于坐标变换,它可以根据给定的操作类型和数值对坐标进行变换。主要应用场景包括但不限于: