zoukankan      html  css  js  c++  java
  • 螺旋队列

    21  22  ...
    20        10
    19        11
    18        12
    17  16  15  14  13

        看清以上数字排列的规律,设 1 点的坐标是 (0,0),x 方向向右为正,y 方向向下为正。例如,7 的坐标为 (-1,-1),2 的坐标为 (0,1),3 的坐标为 (1,1)。编程实现输入任意一点坐标 (x,y),输出所对应的数字。[Finland 某著名通信设备公司 2005 年面试题]

        规律是什么?规律真的一看就能看出来,问题就在于如何利用它。

        先来个大点的:

    很明显这个队列是顺时针螺旋向外扩展的,我们可以把它看成一层一层往外延伸。第 0 层规定为中间的那个 1,第 1 层为 2 到 9,第 2 层为 10 到 25,……好像看出一点名堂来了?注意到 1、9、25、……不就是平方数吗?而且是连续奇数(1、3、5、……)的平方数。这些数还跟层数相关,推算一下就可以知道第 t 层之内(注意:不包括第t层)一共有 (2t-1)^2 个数——即第0层内有1个数,第1层内有1个数,第2层内有9个数...因而第 t 层会从 [(2t-1)^2] + 1 开始继续往外螺旋。给定坐标 (x,y),如何知道该点处于第几层?so easy,层数 t = max(|x|,|y|),例如:(0,1)在第1层为2,(-1,-1)在第1层为7...

        知道了层数,接下来就好办多了,这时我们就知道所求的那点一定在第 t 层这个圈上,顺着往下数就是了。要注意的就是螺旋队列数值增长方向和坐标轴正方向并不一定相同。我们可以分成四种情况——上、下、左、右——或者——东、南、西、北,分别处于四条边上来分析。简单说来就是每一圈数字分为四个区域。

        东|右:x == t,队列增长方向和 y 轴一致,正东方向(y = 0)数值为 (2t-1)^2 + t,所以 v = (2t-1)^2 + t + y

        南|下:y == t,队列增长方向和 x 轴相反,正南方向(x = 0)数值为 (2t-1)^2 + 3t,所以 v = (2t-1)^2 + 3t - x

        西|左:x == -t,队列增长方向和 y 轴相反,正西方向(y = 0)数值为 (2t-1)^2 + 5t,所以 v = (2t-1)^2 + 5t - y

        北|上:y == -t,队列增长方向和 x 轴一致,正北方向(x = 0)数值为 (2t-1)^2 + 7t,所以 v = (2t-1)^2 + 7t + x

        其实还有一点很重要,不然会有大 bug。其它三条边都还好,但是在东边(右边)那条线上,队列增加不完全符合公式!注意到东北角(右上角)是本层的最后一个数,再往下却是本层的第一个数,那当然不满足东线公式啊。怎么办?好办。反正其它三条都满足不是吗,我们把东线的判断放在最后(其实只需要放在北线之后就可以),这样一来,东北角那点始终会被认为是北线上的点啦~

        实现代码如下:

    #include<stdio.h>

    #define max(a,b) ((a)<(b)?(b):(a))
    #define abs(a) ((a)>0?(a):-(a))
    int foo(int x,int y)
    {
       int t=max(abs(x),abs(y));//求出层数t
       int u=t + t;
       int v=u - 1;
       v=v*v+u;//即v = (2t-1)^2 + 2t
       if(x==-t)
         v+=u+t-y;//v = (2t-1)^2 + 5t - y
       else if(y==-t)
         v+=3*u+x-t;//v = (2t-1)^2 + 7t + x
       else if(y==t)
         v+=t-x;//v = (2t-1)^2 + 3t - x
       else 
         v+=y-t;//v = (2t-1)^2 + t + y
       return v;

    }
    void main()

    {
        int x,y;
        for(y=-4;y<=4;y++)
        {
           for(x=-4;x<=4;x++)
             printf("%5d",foo(x,y));
           printf("\n");
         }
         while(scanf("%d%d",&x,&y)==2)
           printf("%d\n",foo(x,y));

         return 0;

    }

     

     

  • 相关阅读:
    Shared Memory in Windows NT
    Layered Memory Management in Win32
    软件项目管理的75条建议
    Load pdbs when you need it
    Stray pointer 野指针
    About the Rebase and Bind operation in the production of software
    About "Serious Error: No RTTI Data"
    Realizing 4 GB of Address Space[MSDN]
    [bbk4397] 第1集 第一章 AMS介绍
    [bbk3204] 第67集 Chapter 17Monitoring and Detecting Lock Contention(00)
  • 原文地址:https://www.cnblogs.com/anderson0/p/1848790.html
Copyright © 2011-2022 走看看