---------------------------------
典型例题 33:C问题---矩阵输出问题
---------------------------------
1 #include <iostream>
2 #include <cstring>
3
4 using namespace std;
5 /*
6 *********************************************
7 $ ./a.out
8 Please Input The N = 6
9 n = 6
10 1 2 9 10 25 26
11 4 3 8 11 24 27
12 5 6 7 12 23 28
13 16 15 14 13 22 29
14 17 18 19 20 21 30
15 36 35 34 33 32 31
16 *********************************************
17 */
18 int matrix_print(int n)
19 {
20 int a[n][n];
21 bzero(a,n*n*sizeof(int));
22 int tag = 0;
23 int count = 2;
24
25 a[0][0] = 1;
26 for(int step = 3; step <= 2*n-1 ; step +=2)
27 {
28 int i,j;
29 if(0 == tag)//顺时针
30 {
31 for (i = 0; i < step/2; ++i)
32 {
33 a[i][step/2] = count++ ;
34 }
35
36 for (j = step/2; j >=0; --j)
37 {
38 a[step/2][j] = count++ ;
39 }
40 tag = 1;
41 }else{//逆时针
42
43 for (i = 0; i < step/2; ++i)
44 {
45 a[step/2][i] = count++;
46 }
47
48 for (j = step/2; j >=0; --j)
49 {
50 a[j][step/2] = count++ ;
51 }
52 tag = 0;
53 }
54 }
55
56 //print the matrix ;
57 cout<<"n = "<<n<<endl;
58 for (int i = 0; i < n; ++i)
59 {
60 for (int j = 0; j < n; ++j)
61 {
62 cout<<a[i][j]<<"/t";
63 }
64 cout<<endl;
65 }
66 return 0;
67 }
68
69 int main(int argc, char * argv[])
70 {
71 int n;
72 cout<<"Please Input The N = ";
73 cin>>n;
74 matrix_print(n);
75 return 0;
76 }
-----------------------
算法思路:想法是想处理1,再按照2,3,4顺时针方面输出,然后按照5,6,7,8,9,
以此类推.(注意规律,每一次的数据个数分别为:1,3,5,7,9...!)
-----------------------
1 #include <cstdio>
2 /*
3 ***********************************************
4 haiping@ubuntu:~/program/yv0928$ ./a.out
5
6 The Array matrix[8][8] is :
7
8 1 28 27 26 25 24 23 22
9
10 2 29 48 47 46 45 44 21
11
12 3 30 49 60 59 58 43 20
13
14 4 31 50 61 64 57 42 19
15
16 5 32 51 62 63 56 41 18
17
18 6 33 52 53 54 55 40 17
19
20 7 34 35 36 37 38 39 16
21
22 8 9 10 11 12 13 14 15
23
24
25 **********************************************
26 */
27
28 void MatrixSpiralOutput(int n)
29 {
30 int **matrix = new int*[n]();
31 for (int idx = 0; idx < n; idx++)
32 {
33 matrix[idx] = new int[n]();
34 }
35
36 int row = 0, col = 0;
37 int i = 0;
38 int len = n * n;
39 int circle = 0;
40
41 while (i < len)
42 {
43 for( ;row < n - circle; row++)
44 matrix[row][col] = ++i;
45
46 row--;
47 col++;
48
49 for( ; col < n - circle; col++)
50 matrix[row][col] = ++i;
51
52 row--;
53 col--;
54
55 for( ; row >= circle; row--)
56 matrix[row][col] = ++i;
57
58 row++;
59 col--;
60
61 for( ;col > circle; col--)
62 matrix[row][col] = ++i;
63
64 row++;
65 col++;
66
67 circle++;
68 }
69
70 printf("/n The Array matrix[%d][%d] is :", n, n);
71 for(int k = 0; k < n; k++)
72 {
73 printf("/n/n ");
74 for(int j = 0; j < n; j++)
75 printf("%-5d", matrix[k][j]);
76 }
77 printf("/n/n");
78
79 for(int idx = 0 ; idx < n ; idx++)
80 delete[] matrix[idx];
81 delete [] matrix;
82
83 }
84
85 int main()
86 {
87 MatrixSpiralOutput(8);
88 return 0;
89 }
---------------
算法思想:这里主要是利用两个变量跟踪相应的下标变化,比较方便,原先我也想用上面的方面,发现比较麻烦
如果想要得到由里到外的螺旋,设定1)i= n*n,2)while(i>0),3)i--,这样就可以了。我原来考虑从里
面往外打印,下标处理很麻烦,看来思维比较......!呵呵
---------------
1 #include <iostream>
2 #include <cstdio>
3 #include <math.h>
4
5 using namespace std;
6 /*
7 ****************************************************
8 haiping@ubuntu:~/program/yv0928$ ./a.out
9 n = 6
10 1 3 4 10 11 21
11 2 5 9 12 20 22
12 6 8 13 19 23 30
13 7 14 18 24 29 31
14 15 17 25 28 32 35
15 16 26 27 33 34 36
16
17 ***************************************************
18 */
19
20 /*
21 ***********************************
22 //获得n*n方阵中第i行第j列个元素
23 int getElement1(int i ,int j,int n)
24 {
25 int num = i+j;
26 int sum = num * (num+1) >>1;
27
28 //过了对角线要另行处理
29 //原作中这里还是有bug,过了对角线,n=3,5,7等后面就不对了
30 if(num > n-1) sum -= (num - n + 1) * (num - n + 1);
31
32 //将判定条件改成 if(!(num&1)),改变方向
33 if(!num & 1) return sum + j+1;
34 return sum + i+1;
35 }
36 ************************************
37 */
38 /*获得n*n方阵中第i行第j列个元素*/
39 int getElement1_m(int i ,int j,int n)
40 {
41 int num = i+j;
42 int sum = num * (num+1) >>1;
43 int s = n*n;
44
45 //过了对角线要另行处理
46 if(num > n-1)
47 {
48 int t = 2*(n-1)-(i+j)+1;
49 s -= t*(t+1)>>1;
50 }
51
52 //将判定条件改成 if(!(num&1)),改变方向
53 if(num & 1) return num > n-1?s +(n-i):sum + j+1;
54 return num > n-1?s + (n-j):sum + i+1;
55 }
56 /*
57 ****************************************************
58 haiping@ubuntu:~/program/yv0928$ ./a.out
59 n = 6
60 1 2 3 4 5 6
61 20 21 22 23 24 7
62 19 32 33 34 25 8
63 18 31 36 35 26 9
64 17 30 29 28 27 10
65 16 15 14 13 12 11
66
67 ***************************************************
68 */
69
70 int getElement2(int i,int j,int n)
71 {
72 int k = min(min(i,j),n-1-max(i,j));
73 int sum = 4 * ( k * (n + 1) - k * (k+1)); /*将判定条件改成 if(j <= i)改变方向*/
74 if(j >= i)
75 sum += (i+j) - 2*k + 1;
76 else
77 sum += ( n - 2*k - 1) * 4 - (i+j) + 2*k + 1;
78 return sum;
79 }
80
81 /*
82 ****************************************************
83 haiping@ubuntu:~/program/yv0928$ ./a.out
84 n = 5
85 2 2 2 2 2
86 2 1 1 1 2
87 2 1 0 1 2
88 2 1 1 1 2
89 2 2 2 2 2
90
91 ***************************************************
92 */
93
94 int getElement3(int i,int j,int n)
95 {
96 //n 为任意正奇数
97 int mid = n/2;
98 return max(abs(i-mid) , abs(j-mid));
99 }
100
101 int main()
102 {
103 int n;
104 int i,j;
105 printf(" n = ");
106 scanf("%d",&n);
107
108 for(i = 0 ; i < n;i++){
109 for(j = 0 ; j < n;j++)
110 printf("%-5d ",getElement1_m(i,j,n));
111 printf("/n");
112 }
113 return 0;
114 }
115
--------------------------------------
算法思路:
(思路来源http://hi.youkuaiyun.com/quietwave博主的回答)
对于这类打印方阵的问题,可以用数学的方法,推导出
a[i][j] = F(i,j)中的F,即将第i行,第j列的元素用 i和j 的函数表示出来
然后再
for(int i = 0 ; i < n;i++)
{
for(int j = 0 ; j < n;j++)
printf("%5d ",getElement(i,j)); printf("/n");
}
关键是完成函数
int getElement(int i,int j);
对于这道题,
可以看出每条副对角线上有 i+j 为常量这个特点
所以可以想象第N条副对角线之前一定有
Sum = 1+2+...+N = N*(N+1)/2 个数字
然后再考虑副对角线i+j的奇偶性,
是奇数则从i=0开始填数,所以a[i][j] = sum + i + 1;
是偶数则有 a[i][j] = sum + j + 1;
方阵改变方向后,则将上面判断奇偶反过来,即可打印