试题链接:PS无限版
题目还是比较简单的,不至于长篇大论的(读题都累死人了),此题要求:有一系列的点(用数组保存下来),编号(1,2……,n),对编号[l,r]的点进行不同的7个操作:
第一个操作还是比较简单的,对编号在[l,r]中的点的坐标分别加a,b即可,即(x,y)——》(x+a,y+b)
在平面坐标系中,围绕一般的点旋转得到新的坐标是很困难的,而坐标系中有一个非常特殊的点,那就是原点,因此,根据第一个操作的提示,旋转中心平移到原点,即(x,y)——》(x-a,x-b),再进行旋转操作得到(x',y'),最后平移回去(x',y')——》(x'+a,y'+a)即可。
简单提一下关于原点旋转操作,因为题目给的角度,即弧度制,弧度制的两要素是点到原点构成的线段与x轴构成的角度和点到直线的距离,旋转后的点距离不变,角度增大θ,而平面坐标x,y分别可以用三角函数构造,即,,其中d为点到原点的距离,为点到原点线段与x轴夹角,最后求解就比较容易了,然后要将弧度制转换为正常坐标,转换方式同理,最后不要忘了平移回去。
同上一题理论,将放缩中心平移到原点,需要操作的点相同位移,点用弧度制表示,此时,此操作变为(此时不用取绝对值),再换回正常坐标平移回去即可
4、5操作有相同的求解方法,写在一起讨论。假设第5个操作为点位移到目的地点的操作,则第4个操作为第5个操作位移之后再位移相同距离,所以,第5个操作解决了,第4个操作就解决了,因此,直接分析第5个操作。
哈哈,没想到吧,这两个操作还是可以用平移+弧度来求解。这次平移直线到经过原点,将直线向下平移个单位长度即可(小于0表示向上),待操作点相同位移,然后利用三角函数性质即可得到目的点弧度表示(,),最后转换,平移。
6、7操作分别用一次变量然后输出即可,没什么难度。
有一个非常苦逼的事是,我本来以为我的解法必然满分的,但是现实却给了残酷的一刀,用python实现以上解法,然后30分超时了,于是我改用了java和c++,70分超时,不得不佩服c++和java
分析与改进:虽然时间超限了,但空间还有很多,因此,满分题解可能是用空间换时间,留给大家讨论交流,我实在想不出怎么优化,或者还有其他更优秀的解法(欢迎大家分享)
python 30分
import math
n, q = map(int, input().split())
point_x = [0.0] * n
point_y = [0.0] * n
for i in range(n):
x, y = map(float, input().split())
point_x[i], point_y[i] = x, y
for _ in range(q):
option = input().split()
id = int(option[0])
l, r = int(option[1]), int(option[2])
if id == 1:
a, b = float(option[3]), float(option[4])
for index in range(l-1, r):
x = point_x[index] + a
y = point_y[index] + b
point_x[index], point_y[index] = x, y
elif id == 2:
a, b, q = float(option[3]), float(option[4]), float(option[5])
for index in range(l - 1, r):
x, y = point_x[index] - a, point_y[index] - b
d = math.sqrt(x ** 2 + y ** 2)
ra = math.atan2(y, x) + q
point_x[index], point_y[index] = d * math.cos(ra) + a, d * math.sin(ra) + b
elif id == 3:
a, b, q = float(option[3]), float(option[4]), float(option[5])
for index in range(l-1, r):
point_x[index], point_y[index] = (point_x[index] - a) * q + a, (point_y[index] - b) * q + b
elif id == 4:
a, b = float(option[3]), float(option[4])
for index in range(l-1, r):
x, y = point_x[index], point_y[index] - b
d = math.sqrt(x**2 + y**2)
ra = 2 * a - math.atan2(y, x)
point_x[index], point_y[index] = d * math.cos(ra), d * math.sin(ra) + b
elif id == 5:
a, b = float(option[3]), float(option[4])
for index in range(l - 1, r):
x, y = point_x[index], point_y[index] - b
ra = math.atan2(y, x) - a
d = math.sqrt(x ** 2 + y ** 2) * math.cos(ra)
point_x[index], point_y[index] = d * math.cos(a), d * math.sin(a) + b
elif id == 6:
print("%.6f" % (sum(point_x[l-1:r]) / (r - l + 1)), "%.6f" % (sum(point_y[l-1:r]) / (r - l + 1)))
elif id == 7:
a, b = float(option[3]), float(option[4])
print("%.6f" % sum([(point_x[index] - a) ** 2 + (point_y[index] - b) ** 2 for index in range(l - 1, r)]))
c++ 70分
#include
#include
#include
using namespace std;
int main() {
int n,p;
cin >> n >> p;
double points[n][2];
for(int i = 0; i < n; i++){
cin >> points[i][0] >> points[i][1];
}
double d,ra;
int id,l,r;
double a,b,s,x,y;
while (p > 0){
cin >> id >> l >> r;
switch (id) {
case 1:
cin >> a >> b;
for (int i = l - 1; i < r; i++) {
points[i][0] += a;
points[i][1] += b;
}
break;
case 2:
cin >> a >> b >> s;
for (int i = l - 1; i < r; i++) {
x = points[i][0] - a;
y = points[i][1] - b;
d = sqrt(x * x + y * y);
ra = atan2(y, x) + s;
points[i][0] = d * cos(ra) + a;
points[i][1] = d * sin(ra) + b;
}
break;
case 3:
cin >> a >> b >> s;
for (int i = l - 1; i < r; i++) {
points[i][0] = (points[i][0] - a) * s + a;
points[i][1] = (points[i][1] - b) * s + b;
}
break;
case 4:
cin >> s >> b;
for (int i = l - 1; i < r; i++) {
x = points[i][0];
y = points[i][1] - b;
d = sqrt(x * x + y * y);
ra = 2 * s - atan2(y, x);
points[i][0] = d * cos(ra);
points[i][1] = d * sin(ra) + b;
}
break;
case 5:
cin >> s >> b;
for (int i = l - 1; i < r; i++) {
x = points[i][0];
y = points[i][1] - b;
ra = atan2(y, x) - s;
d = sqrt(x * x + y * y) * cos(ra);
points[i][0] = d * cos(s);
points[i][1] = d * sin(s) + b;
}
break;
case 6: {
double totalX = 0;
double totalY = 0;
for (int i = l - 1; i < r; i++) {
totalX += points[i][0];
totalY += points[i][1];
}
cout << setiosflags(ios::fixed) << setprecision(6);
cout << totalX / (r - l + 1) << " " << totalY / (r - l + 1) << endl;
}
break;
case 7: {
cin >> a >> b;
double total = 0;
for (int i = l - 1; i < r; i++) {
total += (points[i][0] - a) * (points[i][0] - a) + (points[i][1] - b) * (points[i][1] - b);
}
cout << setiosflags(ios::fixed) << setprecision(6);
cout << total << endl;
}
break;
default:
break;
}
p--;
}
return 0;
}
java 70分
package leetcode;
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int p = scan.nextInt();
double[][] points = new double[n][2];
for(int i = 0; i < n; i++){
points[i][0] = scan.nextDouble();
points[i][1] = scan.nextDouble();
}
int id,l,r;
double a,b,s,x,y;
double d,ra;
while (p > 0){
id = scan.nextInt();
l = scan.nextInt();
r = scan.nextInt();
switch (id){
case 1:
a = scan.nextDouble();
b = scan.nextDouble();
for (int i = l-1; i < r; i++){
points[i][0] += a;
points[i][1] += b;
}
break;
case 2:
a = scan.nextDouble();
b = scan.nextDouble();
s = scan.nextDouble();
for (int i = l-1; i < r; i++) {
x = points[i][0] - a;
y = points[i][1] - b;
d = Math.sqrt(x*x+y*y);
ra = Math.atan2(y,x) + s;
points[i][0] = d * Math.cos(ra) + a;
points[i][1] = d * Math.sin(ra) + b;
}
break;
case 3:
a = scan.nextDouble();
b = scan.nextDouble();
s = scan.nextDouble();
for (int i = l-1; i < r; i++) {
points[i][0] = (points[i][0] - a) * s + a;
points[i][1] = (points[i][1] - b) * s + b;
}
break;
case 4:
s = scan.nextDouble();
b = scan.nextDouble();
for (int i = l-1; i < r; i++) {
x = points[i][0];
y = points[i][1] - b;
d = Math.sqrt(x*x+y*y);
ra = 2 * s - Math.atan2(y, x);
points[i][0] = d * Math.cos(ra);
points[i][1] = d * Math.sin(ra) + b;
}
break;
case 5:
s = scan.nextDouble();
b = scan.nextDouble();
for (int i = l-1; i < r; i++) {
x = points[i][0];
y = points[i][1] - b;
ra = Math.atan2(y, x) - s;
d = Math.sqrt(x*x+y*y) * Math.cos(ra);
points[i][0] = d * Math.cos(s);
points[i][1] = d * Math.sin(s) + b;
}
break;
case 6:
double totalX=0;
double totalY=0;
for (int i = l-1; i < r; i++) {
totalX += points[i][0];
totalY += points[i][1];
}
System.out.printf("%.6f %.6f\n",totalX/(r-l+1),totalY/(r-l+1));
break;
case 7:
double total = 0;
a = scan.nextDouble();
b = scan.nextDouble();
for (int i = l-1; i < r; i++) {
total += (points[i][0] - a) * (points[i][0] - a) + (points[i][1] - b) * (points[i][1] - b);
}
System.out.printf("%.6f\n", total);
break;
}
p--;
}
}
}
因为这道题,让我意识到,同样的解法,不同的语言会可能会得到不一样的分数,所以有些题没拿到满分可以考虑换一种语言。
最后,求打赏