[Simple] 方阵由外向内旋转排列,打印

问题要求:输入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是偶数时不会有绿色):

 

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

 

 

设橙色为left,粉色为right,可以看出如下规律:

在矩阵上半块(若为奇数包含中间行)

----橙色左边的每一个值都比自己上面的小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[N];
        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;
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值