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\n",ansx,ansy); } } return 0; }