数学之美——矩阵旋转

这几天在疯狂用C++学习和练习算法,昨天刷完了一道北航的研究生上机题目,觉得很有意思。之后查看了一下别人都是怎么想这些问题的,现在就是觉得数学非常美,有了数学好像好多问题,都不用去记忆规律或者推导规律了。
问题:如何将一个矩阵旋转0,90,180,270度?或许这个问题你接触过烂熟于心,或许你觉得可以花时间加以推导还是可以推出来,或者你和我一样,最开始拿到这个问题并没有自信one-take就搞出来。但如果你对矩阵论有所了解,你会发现以下方法给了你一定的perspective。总而言之,就是找到基向量的位置。在通过旋转基向量来旋转矩阵。旋转矩阵按列向量来思考会简单一些。
matrix
如果在实际编程中,遇到数组,因为数组的index不能为负,比如10*10的数组,旋转后整体应该移了10个单位。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<stdio.h>
void print(int a[][10]){
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
printf("%3d",a[i][j]);
}
printf("\n");
}
}
int main(){
int a[10][10];
int k = 0;
//原图像
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
a[i][j] = k++;
}
}
//顺时针旋转90
int shun90[10][10];
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
shun90[j][9-i] = a[i][j];
}
}
//逆时针旋转90
int ni90[10][10];
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
ni90[9-j][i] = a[i][j];
}
}
//旋转180
int zhuan180[10][10];
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
zhuan180[9-i][9-j] = a[i][j];
}
}
printf("原矩阵\n\n");
print(a);
printf("\n\n顺时针90\n\n");
print(shun90);
printf("\n\n逆时针90\n\n");
print(ni90);
printf("\n\n转180\n\n");
print(zhuan180);
return 0;
}

而在面对面试或者机考的时候,简单记住(i,j)==>(j,-i),(-i,-j),(-j,i)这样的映射关系就好了,举个例子就知道应该映射到哪个位置。同理,在给出两个矩阵让你判断他们是否是旋转关系,如果是,旋转多少度也可以通过这个关系直接判断。这就是北航那个题目了。这里也简单贴出核心代码吧。

1
2
3
4
5
6
7
8
9
int flag[4]={1,1,1,1};  /**标记0,90,180,270四个方向*/
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
if(a[i][j]!=b[i][j]) flag[0]=0;
if(a[n-1-j][i]!=b[i][j]) flag[1]=0;
if(a[n-1-i][n-1-j]!=b[i][j]) flag[2]=0;
if(a[j][n-1-i]!=b[i][j]) flag[3]=0;
}