回 帖 发 新 帖 刷新版面

主题:[原创]分享:正方形的蛇形矩阵 - 个人思路分享

思路分享:

是因为看见贴子:
[url=http://bbs.pfan.cn/post-275699.html][原创]蛇形矩阵---抛砖引玉[/url]

所以,小弟也想来试试。

下面是一个 7 x 7 的蛇形正方的矩阵:

  49  48  44  43  35  34  22
  47  45  42  36  33  23  21
  46  41  37  32  24  20  11
  40  38  31  25  19  12  10
  39  30  26  18  13   9   4
  29  27  17  14   8   5   3
  28  16  15   7   6   2   1

因为小弟想写个省内存些的算法。
所以就不打算用数组来存这些生成好的数了。

小弟知道,想要文字输出的话,通常都是从左到右,从上到下的。
所以,小弟打算把矩阵的数,从左到右,从上到下的算出来。这样的话就不需要数组来存这些数了嘛。

小第先算了一下,从矩阵的前后两个数的差。
得到的结果如下:

49 - 48 = 1
48 - 44 = 4
44 - 43 = 1
43 - 35 = 8
35 - 34 = 1
34 - 22 = 12

排成一排就是:


  49   48   44   43   35   34    22
     1    4    1    8    1    12


下面几行也差不多的:



 47   45   42   36   33   23   21
    2    3    6    3   10    2

 46   41   37   32   24   20   11
    5    4    5    8    4    9

 40   38   31   25   19   12   10
    2    7    6    6    7    2

 39   30   26   18   13    9    4
    9    4    8    5    4    5

 29   27   17   14    8    5    3
    2   10    3    6    3    2

 28   16   15    7    6    2    1
   12    1    8    1    4    1



这样的话,就得到这样一个矩阵了:

     1    4    1    8    1   12

     2    3    6    3   10    2

     5    4    5    8    4    9

     2    7    6    6    7    2

     9    4    8    5    4    5

     2   10    3    6    3    2

    12    1    8    1    4    1

那么,来看看这个矩阵有什么规律吗?

先把矩阵按对角线分成两半看看吧:


     1    4    1    8    1   12
                             /
                            / 
                           /  
     2    3    6    3   10/   2
                         /    
                        /     
                       /      
                      /       
     5    4    5    8/   4    9
                    /         
                   /          
                  /           
                 /            
     2    7    6/   6    7    2
               /               
              /                
             /                 
     9    4 /  8    5    4    5
           /                    
          /                     
         /                      
    2   /10    3    6    3    2
       /                       
      /                        
     /                         
    12    1    8    1    4    1
                               

怎么样,看到规律了吗?

上面的矩阵就是两个一样的三角的数阵拼成的。
推出一个三角的数阵就能得出另一个了。

这样,再把两个三角的数阵组合起来就可以推出小弟想要的蛇形正方矩阵了。

再来就是如何成生那个“三角”的数阵了。


     1    4    1    8    1   12

     2    3    6    3   10

     5    4    5    8

     2    7    6

     9    4

     2

大家看出来规律了吗?

这个数阵还能再分成两个数阵。

第一个:

     1         1         1    

          3         3    

     5         5     

          7     

     9     


第二个:

          4         8        12

     2         6        10

          4         8

     2         6

          4

     2

哈哈,再在规律很显示了吧。

给这个数阵再加个坐标吧。


    x=1    2    3    4    5 
y:
1    1         1         1    

2         3         3    

3    5         5     

4         7     

5    9     


这个阵中的数嘛,就是相对的 y 坐标值的二倍再减一:(y * 2 - 1)
由于在计算机中,加法比乘法快,所以小弟把上面的算式改成:(y + y - 1)

这样就会快一些了。

第二个阵呢,也差不多。

值于位置的关系是:(2 * x),小弟我用(x + x)。

这样的话,还有一个问题呢!

两个数阵怎么穿起来呢?


   x=1    2    3    4    5    6
y:
1    1    4    1    8    1   12

2    2    3    6    3   10

3    5    4    5    8

4    2    7    6

5    9    4

6    2


小弟我发现,在数阵一的地方,它的位置总是 要么 x,y 都为偶数,要么都为奇数。
所以,小弟我想出这么一个式子:

( x mod 2 xor y mod 2 )

这样的话,框架就出来了。

if 这个式子 then
    数阵一
else
    数阵二
end if 

再把刚才推出来的数阵的式子填进去:

IF x mod 2 xor y mod 2 THEN
    v = y + y - 1
ELSE
    v = x + x
END IF


这样就好了吗?

没有哦!
还没有对这个三角数阵进行形状的控制。

不控制的话,输出的就不是三角的数阵了。

所以,小弟想出了这么一个框架:

IF wid - y >= x THEN
    正的数阵
ELSE
    倒的数阵
END IF

正的数阵说过了,倒的数阵小弟就不多了。

最后,形成的代码就是:

CLS
INPUT wid
FOR Y = 1 TO wid
    PRINT USING "####"; v;
    FOR X = 1 TO wid - 1
        IF wid - Y >= X THEN
            IF X MOD 2 XOR Y MOD 2 THEN v = X + X ELSE v =Y + Y - 1
        ELSE
            IF X MOD 2 XOR Y MOD 2 THEN v = (wid - Y) * 2 + 1 ELSE v = (wid - X) * 2
        END IF
        PRINT USING "####"; v;
    NEXT X
    PRINT
NEXT Y
END

这样就完成了吗?

不对,因为输出的数组不是蛇形矩阵了。

但是,规律己经出来了。
所以,只要这样就OK了。

ot = ot - v
'ot 就是 out 的简写,因为 OUT 在 QB 里己有其它的意义了。

把上面的算式代入上面的代码中:

CLS
INPUT wid
sz = wid * wid
FOR Y = 1 TO wid
    PRINT USING "####"; v;
    FOR X = 1 TO wid - 1
        IF wid - Y >= X THEN
            IF X MOD 2 XOR Y MOD 2 THEN v = X + X ELSE v =Y + Y - 1
        ELSE
            IF X MOD 2 XOR Y MOD 2 THEN v = (wid - Y) * 2 + 1 ELSE v = (wid - X) * 2
        END IF
        ot = ot - v
        PRINT USING "####"; ot;
    NEXT X
    PRINT
NEXT Y
END

输出果不对哦。为什么呢?

因为小弟我很找了横向的规律,纵向的还没有找出来的。

别急,马上就找出来了。

 49   48   44   43   35   34   22
    1    4    1    8    1   12

 47   45   42   36   33   23   21
    2    3    6    3   10    2

 46   41   37   32   24   20   11
    5    4    5    8    4    9

 40   38   31   25   19   12   10
    2    7    6    6    7    2

 39   30   26   18   13    9    4
    9    4    8    5    4    5

 29   27   17   14    8    5    3
    2   10    3    6    3    2

 28   16   15    7    6    2    1
   12    1    8    1    4    1

其中,奇行中的第一个数:
47 = 49 - 2
40 = 49 - 2 - 5
29 = 49 - 2 - 5 - 2 - 9

偶行中的第一个数:
46 = 47 - 1
39 = 40 - 1
28 = 29 - 1

好了。
把这个规律加进去就形成小弟最后的代码了。

CLS
INPUT wid
sz = wid * wid
FOR Y = 1 TO wid
    ot = sz: PRINT USING "####"; ot;
    IF Y MOD 2 THEN sz = sz - Y - Y ELSE sz = sz - 1
    FOR X = 1 TO wid - 1
        IF wid - Y >= X THEN
            IF X MOD 2 XOR Y MOD 2 THEN ot = ot - (X + X) ELSE ot = ot - (Y + Y - 1)
        ELSE
            IF X MOD 2 XOR Y MOD 2 THEN ot = ot - ((wid - Y) * 2 + 1) ELSE ot = ot - (wid - X) * 2
        END IF
        PRINT USING "####"; ot;
    NEXT X
    PRINT
NEXT Y
END

以上是小弟的个人思路,要是不对的话,还请大家多多指点。

回复列表 (共2个回复)

沙发

嗯,分析得很不错,继续努力。

板凳

谢谢 moz 的鼓励。

因为是 moz 的鼓励,所以价值不同。

我来回复

您尚未登录,请登录后再回复。点此登录或注册