Matrix67大牛关于矩阵经典题目的链接:http://www.matrix67.com/blog/archives/276/
nyoj 298 点的变换
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=298
经典题目1
给定n个点,m个操作,构造O(m+n)的算法输出m个操作后各点的位置。操作有平移、缩放、翻转和旋转
这里的操作是对所有点同时进行的。其中翻转是以坐标轴为对称轴进行翻转(两种情况),旋转则以原点为中心。如果对每个点分别进行模拟,那么m个操作总共耗
时O(mn)。利用矩阵乘法可以在O(m)的时间里把所有操作合并为一个矩阵,然后每个点与该矩阵相乘即可直接得出最终该点的位置,总共耗时
O(m+n)。假设初始时某个点的坐标为x和y,下面5个矩阵可以分别对其进行平移、旋转、翻转和旋转操作。预先把所有m个操作所对应的矩阵全部乘起来,
再乘以(x,y,1),即可一步得出最终点的位置。
注意:m个操作的矩阵连乘时必须左乘
代码如下:
1 #include<stdio.h> 2 #include<math.h> 3 #include<string.h> 4 #define N 5 5 struct Matrix 6 { 7 double a[N][N]; 8 }res,tmp,origin,ans,point[10000]; 9 Matrix mul(Matrix x,Matrix y) //矩阵乘法 10 { 11 int i,j,k; 12 memset(tmp.a,0,sizeof(tmp.a)); 13 for(i=1;i<=3;i++) 14 for(j=1;j<=3;j++) 15 for(k=1;k<=3;k++) 16 tmp.a[i][j]+=x.a[i][k]*y.a[k][j]; 17 return tmp; 18 } 19 int main() 20 { 21 int i,j,n,m; 22 char c; 23 double x,y,ang; 24 scanf("%d%d",&n,&m); 25 for(i=1;i<=n;i++) //相当于 |x| 26 { // |y| 27 scanf("%lf%lf",&point[i].a[1][1],&point[i].a[2][1]); // |1| 28 point[i].a[3][1]=1; 29 } 30 memset(res.a,0,sizeof(res.a)); //初始化为单位矩阵 31 for(i=1;i<=3;i++) 32 res.a[i][i]=1; 33 for(i=1;i<=m;i++) //将m个操作的矩阵连乘 34 { 35 getchar(); 36 scanf("%c",&c); 37 memset(origin.a,0,sizeof(origin.a)); //初始化为单位矩阵 38 for(j=1;j<=3;j++) 39 origin.a[j][j]=1; 40 if(c=='M') 41 { //移动:相当于 |1 0 x| 42 scanf("%lf%lf",&x,&y); // |0 1 y| 43 origin.a[1][3]=x; // |0 0 1| 44 origin.a[2][3]=y; 45 } 46 else if(c=='X') //绕x轴旋转:相当于 |1 0 0| 47 origin.a[2][2]=-1; // |0 -1 0| 48 // |0 0 1| 49 50 else if(c=='Y') //绕x轴旋转:相当于 |-1 0 0| 51 origin.a[1][1]=-1; // |0 1 0| 52 // |0 0 1| 53 54 else if(c=='S') //缩放:相当于 |x 0 0| 55 { // |0 x 0| 56 scanf("%lf",&x); // |0 0 1| 57 origin.a[1][1]=x; 58 origin.a[2][2]=x; 59 } 60 else 61 { //旋转:相当于 |cos(@) -sin(@) 0| 62 scanf("%lf",&x); // |sin(@) cos(@) 0| 63 ang=x/180*acos(-1.0); // |0 0 1| 64 origin.a[1][1]=cos(ang); 65 origin.a[1][2]=-sin(ang); 66 origin.a[2][1]=sin(ang); 67 origin.a[2][2]=cos(ang); 68 } 69 res=mul(origin,res); //矩阵必须左乘 70 } 71 for(i=1;i<=n;i++) 72 { 73 ans=mul(res,point[i]); //连乘后的矩阵乘以点的坐标 74 printf("%.1f %.1f\n",ans.a[1][1],ans.a[2][1]); 75 } 76 return 0; 77 }
来源:https://www.cnblogs.com/frog112111/archive/2013/05/15/3080678.html