矩阵十题(1)

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 }
View Code

 

posted on 2013-05-15 20:25  jumpingfrog0  阅读(804)  评论(0编辑  收藏  举报

导航