坐标变换1
问题:对给定的初始坐标进行所有的平移操作,然后输出最终的坐标。
输入:操作数,坐标数;
操作;
坐标。
输出:变换后的坐标。
自己的思路
用二维向量存储输入,然后遍历两个二维向量,执行操作,再输出。
有点笨,有点傻。
优秀的思路
对每一个点的操作是一样的,都是多次平移,平移操作可以累加,直接讲所有的操作合并,然后每个点执行一次平移即可。
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector<vector<int> > T(n,vector<int>(2));
vector<vector<int> > Points(m,vector<int>(2));
for(int i=0; i<n; i++){
for(int j=0; j<2; j++){
cin>>T[i][j];
}
}
for(int i=0; i<m; i++){
for(int j=0; j<2; j++){
cin>>Points[i][j];
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
Points[i][0]+=T[j][0];
Points[i][1]+=T[j][1];
}
}
for(int i=0;i<m;i++){
cout<<Points[i][0]<<" "<<Points[i][1]<<endl;
}
return 0;
}
get:
学会简化重复的操作,能合并的要合并起来,减少开销。
坐标变换2
问题:两种操作,拉伸、旋转,对每个点执行指定的连续的操作序列,给出最后的变换结果。
输入:操作数,查询点数
操作(种类,实数值:k、弧度)
起始操作下标,终止操作下标,x,y
输出:变换后的点
我的思路
所有的操作存起来,然后循环接收点的时候,对每个点进行一系列操作,结果存储起来,最终输出。
不长记性,重复的操作一直做,有点笨,而且试了,运行结果会超时。因为旋转调用很多次cos sin函数,估计
优秀的思路
https://blog.csdn.net/reidpa/article/details/133746414
操作可以分别积累,因为每个点的操作都是操作序列的连续的一段,可以先处理操作序列。真的很巧妙。
拉伸的操作累乘起来,截取一部分就是,把不在的前面部分除掉就可以。
旋转操作可以累加起来,截取一部分,就是把不做的那部分减掉就好。
然后就可以只对点做一次拉伸和一次旋转。
#include <iostream>
#include <vector>
#include <math.h>
#include <utility>
#include <iomanip>
using namespace std;
int main(){
int n_opts,m_points;
cin >> n_opts >> m_points;
int type;
double value;
double op1_list[n_opts + 1] = {1}, op2_list[n_opts + 1] = {0};
// 操作合并
for(int i = 1; i <= n_opts; i++){
cin >> type >> value;
if(type == 1){
op1_list[i] = op1_list[i - 1] * value;
op2_list[i] = op2_list[i - 1];
}
else {
op1_list[i] = op1_list[i - 1];
op2_list[i] = op2_list[i - 1] + value;
}
}
int op_s, op_e;
double x, y;
double op1 , op2;
vector<vector<double> > ans(m_points + 1, vector<double>(2));
for(int i = 1; i <= m_points; i++){
cin >> op_s >> op_e >> x >> y;
op1 = op1_list[op_e] / op1_list[op_s - 1];
op2 = op2_list[op_e] - op2_list[op_s - 1];
x *= op1;
y *= op1;
double x2,y2;
x2 = x * cos(op2) - y * sin(op2);
y2 = x * sin(op2) + y * cos(op2);
ans[i][0] = x2;
ans[i][1] = y2;
}
for(int i = 1; i <= m_points; i++){
cout << fixed << setprecision(3) << ans[i][0] << " " << fixed << setprecision(3) << ans[i][1] << endl;
}
return 0;
}
get:
①循环里面的重复操作要想办摘出来,就像这个题,如果对每个点的每个旋转都单独操作,要调用cos和sin函数很多次,时间开支很大,就会超时
②旋转操作里要注意值的得跟新,新的x、y的计算都需要用到原来的x、y,所以要另外用新的变量来存储结果。
③不用把所有的值都存储起来,可以拿到就进行操作,结果存储起来就好。
④最初自己的想法是有用到一个新的类型,pair,可以存储类型不同的数据对,结合vector,用来存储操作对
vector<pair<int,double> > opts(n_opts + 1);
if(opts[j].first == 1){
x = opts[j].second * x;
y = opts[j].second * y;
}