矩阵十题(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),即可一步得出最终点的位置。

矩阵十题(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

 

你可能感兴趣的:(矩阵)