[Simple] 方阵由外向内旋转排列,打印
2009-11-03 15:24
232 查看
问题要求:输入N,打印N*N方阵,旋转着向内排列,最后到中心。
例如:
输入:3
输出:
1 2 3
8 9 4
7 6 5
输入:4
输出:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
解决方案:
如果用模拟法,就是先开辟一个N*N的二维数组,全部初始化为0,然后模拟这个旋转——沿着一个方向添数字,遇到不为0的数,改变方向,继续遇到不为0的数,再改变方向……从实现上考虑,思路简单,但是空间占用率太大,当N很大时,这个方案不可行。
其实这种问题凭空想还真的不好做,但是用笔在纸上画画就明白了。我画了一个7*7和一个8*8的矩阵。可以发现整个图案大致是一个X形状,也就是说,大致沿着对角线(并不是完全沿着)可以将矩阵分为4个部分,每个部分都是沿着一个方向的递增或递减。那么我们只要把散布在X上的数字计算出来,它们之间的数字按照规律填充就可以了,其实也就是说,我们可以一行一行的处理,每次打印一行,而这一行只需要计算两个值。
举个7*7的例子(彩色代表要计算的值,绿色代表两个值相同,N是偶数时不会有绿色):
设橙色为left,粉色为right,可以看出如下规律:
在矩阵上半块(若为奇数包含中间行)
----橙色左边的每一个值都比自己上面的小1
----橙色右边,粉色左边,每一个值都比自己左边大1
----粉色右边的每一个值都比自己上面的大1
矩阵下半块
----粉色左边的每一个值都比自己上面的小1
----粉色右边,橙色左边,每一个值都比自己左边小1
----橙色右边的每一个值都比自己上面的大1
橙色和粉色的值可以按照相邻递进差的规律,找出和行的关系,下面是我的代码。
例如:
输入:3
输出:
1 2 3
8 9 4
7 6 5
输入:4
输出:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
解决方案:
如果用模拟法,就是先开辟一个N*N的二维数组,全部初始化为0,然后模拟这个旋转——沿着一个方向添数字,遇到不为0的数,改变方向,继续遇到不为0的数,再改变方向……从实现上考虑,思路简单,但是空间占用率太大,当N很大时,这个方案不可行。
其实这种问题凭空想还真的不好做,但是用笔在纸上画画就明白了。我画了一个7*7和一个8*8的矩阵。可以发现整个图案大致是一个X形状,也就是说,大致沿着对角线(并不是完全沿着)可以将矩阵分为4个部分,每个部分都是沿着一个方向的递增或递减。那么我们只要把散布在X上的数字计算出来,它们之间的数字按照规律填充就可以了,其实也就是说,我们可以一行一行的处理,每次打印一行,而这一行只需要计算两个值。
举个7*7的例子(彩色代表要计算的值,绿色代表两个值相同,N是偶数时不会有绿色):
1 | 2 | 3 | 4 | 5 | 6 | 7 |
24 | 25 | 26 | 27 | 28 | 29 | 8 |
23 | 40 | 41 | 42 | 43 | 30 | 9 |
22 | 39 | 48 | 49 | 44 | 31 | 10 |
21 | 38 | 47 | 46 | 45 | 32 | 11 |
20 | 37 | 36 | 35 | 34 | 33 | 12 |
19 | 18 | 17 | 16 | 15 | 14 | 13 |
在矩阵上半块(若为奇数包含中间行)
----橙色左边的每一个值都比自己上面的小1
----橙色右边,粉色左边,每一个值都比自己左边大1
----粉色右边的每一个值都比自己上面的大1
矩阵下半块
----粉色左边的每一个值都比自己上面的小1
----粉色右边,橙色左边,每一个值都比自己左边小1
----橙色右边的每一个值都比自己上面的大1
橙色和粉色的值可以按照相邻递进差的规律,找出和行的关系,下面是我的代码。
#include <stdio.h> void PRline(int* s, int count) { int* end = s + count; while(s < end) printf("%d/t",*s++); printf("/n"); } int Arrange(int N) { int* line = new int ; int i, left, right, row; for( i = 0; i < N; ++i ) line[i] = i + 1; PRline( line, N ); for( left = 0, right = N-1, row = 1; left < N/2; ++left, --right, ++row ) { for( i = 0; i < left; ++i ) --line[i]; line[left] = 4 * row * ( N - row ); for( i = left + 1; i < right; ++i ) line[i] = line[i-1] + 1; line[right] = 2 * ( row -1 ) * ( 2 * N - 2 * row + 1 ) + N + 1; for( i = right + 1; i < N; ++i ) ++line[i]; PRline( line, N ); } for( ; left < N - 1; ++left, --right, ++row ) { for( i = 0; i < right; ++i ) --line[i]; line[right] = 3 * ( N - 1 ) + ( N - 1 - row ) * ( 4 * row - 2 ); for( i = right + 1; i < left; ++i ) line[i] = line[i-1] - 1; line[left] = 2 * N + 4 * row * ( N - 1 - row ); for( i = left + 1; i < N; ++i ) ++line[i]; PRline( line, N ); } delete []line; return 1; } int main() { int N; do{ printf("please input Number: "); scanf("%d", &N); if( N <= 0 ) break; Arrange(N); }while(1); return 0; }
相关文章推荐
- (下)--螺旋矩阵的打印---由外向内旋转的八种情况
- 从右上角到左下角沿反对角线打印方阵中的元素
- 打印一个N*N的方阵,N为每边字符的个数( 3〈N〈20 ),要求最外层为“X”,第二层为“Y”,从第三层起每层依次打印数字0,1,2,3,...
- 写一方法,打印等长的二维数组,要求从1开始的自然数由方阵的最外圈向内螺旋方式地顺序排列。 如: n = 4 则打印:
- 用C语言实现顺时针螺旋方阵的打印(含算法)
- 集合的全排列问题-递归实现方式的改进---旋转法
- 数字旋转方阵 分治法
- 用1、2、3、3、4、5这六个数字,用java写一个程序,打印出所有不同的排列 要求:"4"不能在第三位,"3"与"5"不能相连。
- 由外向内顺时针&逆时针旋转矩阵
- 一个打印输入字符串所有排列的递归程序
- Java实现——顺时针打印N阶方阵
- 方阵旋转--蓝桥杯
- 打印等长的二维数组,要求从1开始的自然数由方阵的最外圈向内螺旋方式地顺序排列。
- 给定字符串,打印出组成字符串的字符的全排列
- 数字方阵的旋转填充(递归方法)
- BZOJ4714 : 旋转排列
- 旋转打印矩阵。这个题目我见过很多次都是放弃了。
- 用1、2、2、3、4、5这六个数字,打印出所有不同的排列
- 打印螺旋排列的数字
- Java实现:按要求打印数组的排列情况