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
