NYOJ 298

利用矩阵来做变换,参考Max大神的思想的,虽然不是同一道题。

-----------

给定n个点,m个操作,构造O(m+n)的算法输出m个操作后各点的位置。操作有平移、缩放、翻转和旋转
    这里的操作是对所有点同时进行的。其中翻转是以坐标轴为对称轴进行翻转(两种情况),旋转则以原点为中心。如果对每个点分别进行模拟,那么m个操作总共耗时O(mn)。利用矩阵乘法可以在O(m)的时间里把所有操作合并为一个矩阵,然后每个点与该矩阵相乘即可直接得出最终该点的位置,总共耗时O(m+n)。假设初始时某个点的坐标为x和y,下面5个矩阵可以分别对其进行平移、旋转、翻转和旋转操作。预先把所有m个操作所对应的矩阵全部乘起来,再乘以(x,y,1),即可一步得出最终点的位置。

转自M67大神

------

以下是NYOJ的练习题

感觉这种做法是十分巧妙的。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
struct Matrax {
	double m[3][3];
};
double PI;
struct Point {
	double x,y;
}p[10100];


void init(Matrax &p){
	for(int i=0;i<3;i++)
	for(int j=0;j<3;j++)
	p.m[i][j]=0;
}

Matrax enM(double L,double P){
	Matrax c;
	init(c);
	c.m[0][0]=c.m[1][1]=c.m[2][2]=1;
	c.m[0][2]=L;c.m[1][2]=P;
	return c;
}

Matrax enX(){
	Matrax c;
	init(c);
	c.m[1][1]=-1; 
	c.m[0][0]=c.m[2][2]=1;
	return c;
}

Matrax enY(){
	Matrax c;
	init(c);
	c.m[0][0]=-1; 
	c.m[1][1]=c.m[2][2]=1;
	return c;
}

Matrax enS(double P){
	Matrax c;
	init(c);
	c.m[1][1]=P; 
	c.m[0][0]=P;c.m[2][2]=1;
	return c;
}

Matrax enR(double R){
	Matrax c;
	init(c);
	c.m[0][0]=cos(R);c.m[0][1]=-1*sin(R);
	c.m[1][0]=sin(R);c.m[1][1]=cos(R);
	c.m[2][2]=1; 
	return c;
}

Matrax multi(Matrax a,Matrax b){
	Matrax c;
	for(int i=0;i<3;i++){
		for(int j=0;j<3;j++){
			c.m[i][j]=0;
			for(int k=0;k<3;k++)
			c.m[i][j]+=a.m[i][k]*b.m[k][j];
		}
	}
	return c;
}

int main(){
	PI=acos(-1.0);
	int N,M;
	double ts[3];
	char t; double x,y,L,P,R;
	while(scanf("%d %d",&N,&M)!=EOF){
		Matrax ans;
		init(ans);
		ans.m[0][0]=ans.m[1][1]=ans.m[2][2]=1;
		for(int i=0;i<N;i++)
		scanf("%lf%lf",&p[i].x,&p[i].y);
		for(int i=0;i<M;i++){
			cin>>t;
			Matrax tt;
			if(t=='X'){
				tt=enX();
				ans=multi(tt,ans);
			}
			else if(t=='Y'){
				tt=enY();
				ans=multi(tt,ans);
			}
			else if(t=='M'){
				scanf("%lf%lf",&L,&P);
				tt=enM(L,P);
				ans=multi(tt,ans);
			}
			else if(t=='S'){
				scanf("%lf",&P);
				tt=enS(P);
				ans=multi(tt,ans);
			}
			else if(t=='R'){
				scanf("%lf",&R);
				R=PI*R/180.0;
				tt=enR(R);
				ans=multi(tt,ans);
			}
		}
		for(int i=0;i<N;i++){
			ts[0]=p[i].x; ts[1]=p[i].y; ts[2]=1;
			double ansx=ts[0]*ans.m[0][0]+ts[1]*ans.m[0][1]+ts[2]*ans.m[0][2];
			if(fabs(ansx-0)<1e-8) ansx=0;
			double ansy=ts[0]*ans.m[1][0]+ts[1]*ans.m[1][1]+ts[2]*ans.m[1][2];
			if(fabs(ansy-0)<1e-8) ansy=0;
			printf("%.1lf %.1lf
",ansx,ansy);
		}
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/jie-dcai/p/3950674.html