一时技痒 不用模拟第一印象的构造 通过三个观察得来的规律解决N^2个往返接力问题...

原文链接:http://www.cnblogs.com/waynebaby/archive/2009/07/25/1530653.html 问题原题  见银河使者的随笔  http://www.cnblogs.com/nokiaguy/archive/2009/07/24/1530139.html
第一印象  我得到了和他一样的解法,就是用斜切片,每一层的 x-1和y+1  来控制顺序写数字的笔落在哪一个坐标。
但是根据一段时间的观察  我发现了几个规律 可以让我们不用模拟整个顺序的流

首先我们观察每一个切片
1 3 4 10 11 21 22 36 37 55
2 5 9 12 20 23 35 38 54 56
6 8 13 19 24 34 39 53 57 72
7 14 18 25 33 40 52 58 71 73
15 17 26 32 41 51 59 70 74 85
16 27 31 42 50 60 69 75 84 86
28 30 43 49 61 68 76 83 87 94
29 44 48 62 67 77 82 88 93 95
45 47 63 66 78 81 89 92 96 99
46 64 65 79 80 90 91 97 98 100
我们发现 在 n,n 坐标上的每一个数字都是这个切片对称 而且是平均值。 经过简单的计算  我们发现 1-n个切片的平均值 都是(n*n +1)/2

继续观察 又发现规律了。  这个矩阵对角对称的任意两个格子   正好是距离整个数列中心距离相等的两点  比如1和100 20和81   他们的和必为 max*max +1

这样我们只要能推算出某一行或者某一列的值   就可以通过上面两个特征来生成整个矩阵了哦



但是这个矩阵的行列太乱了 很难找出规律 这个时候就要考虑更简单的模型
我们看看非首尾接力的矩阵

1

1 2
3

1 2 4
3 5
6

1 2 4 7
3 5 8
6 9
10

有没有发现  粗体的数字 刚好是之前所有斜切片的总和?
那么 顺序矩阵和接力矩阵 有什么异同呢?

1 3 4 10 11 21 22 36 37 55
2 5 9 12 20 23 35 38 54 56
6 8 13 19 24 34 39 53 57 72
7 14 18 25 33 40 52 58 71 73
15 17 26 32 41 51 59 70 74 85
16 27 31 42 50 60 69 75 84 86
28 30 43 49 61 68 76 83 87 94
29 44 48 62 67 77 82 88 93 95
45 47 63 66 78 81 89 92 96 99
46 64 65 79 80 90 91 97 98 100

我们可以把接力矩阵当成隔行反转的顺序矩阵。这样我们就得到了一个在 x,y轴上摆动的参考值。  有了参考值  就可以根据前两点进行矩阵生成了

一时技痒 不用模拟第一印象的构造 通过三个观察得来的规律解决N^2个往返接力问题...一时技痒 不用模拟第一印象的构造 通过三个观察得来的规律解决N^2个往返接力问题...Code
   static void Main(string[] args)
        {
            var max = 11;
            int [,] mx=new int [max,max];
            var sideval = 0;
            for (var seed = 0; seed < max; seed++)
            {
               
                int parevalue = (seed + 1) * (seed + 1) + 1;//规律1 中心轴对称两数之和等于层数平方+1 
                bool isOdd = seed % 2 == 1;

                sideval = sideval + seed + 1;   //规律2 两边至少有一个数字为 1+2+3+4+一时技痒 不用模拟第一印象的构造 通过三个观察得来的规律解决N^2个往返接力问题...+n
                for (var fillseed = seed; fillseed >=0; fillseed--)
                {

                    int row, col;
                    if (!isOdd)
                    {
                        row = fillseed;
                        col = seed - fillseed;

                    }
                    else
                    {
                        col = fillseed;
                        row = seed - fillseed;
                    }
                    //规律1 中心轴对称两数之和等于层数平方+1 
                    mx[col, row] = sideval - fillseed;
                    mx[row, col] = parevalue - mx[col, row];  
                    //规律3 中心对称的和为 max*max+1
                    mx[max - col - 1, max - row - 1] = max * max +1 - mx[col, row];
                    mx[max - row - 1, max - col - 1] = max * max + 1 - mx[row, col];

                }

            }

            for (var x = 0; x < max; x++)
            {
                for (var y = 0; y < max; y++)
                {
                    Console.Write(string.Format (" {0:d3}" ,mx[x, y]));
    

                }

                Console.WriteLine();

            }

                Console.Read();

        }
解法有很多种  这种无疑是很生涩的。 作为面试题目的话  并不建议写这种考官很难理解的解法,会有小鞋

作为头脑风暴  防止老年痴呆 这个还是有一定意义的

转载于:https://www.cnblogs.com/waynebaby/archive/2009/07/25/1530653.html

上一篇:随机数种子random.seed()理解


下一篇:php 依赖注入的实现