csp 23-09-1&2 坐标变换*2

坐标变换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;
}
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值