螺旋隊列

 

 

 

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 年面試題]html

    規律是什麼?規律真的一看就能看出來,問題就在於如何利用它。面試

    先來個大點的:編程

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

    很明顯這個隊列是順時針螺旋向外擴展的,咱們能夠把它當作一層一層往外延伸。第 0 層規定爲中間的那個 1,第 1 層爲 2 到 9,第 2 層爲 10 到 25,……好像看出一點名堂來了?注意到 一、九、2五、……不就是平方數嗎?並且是連續奇數(一、三、五、……)的平方數。這些數還跟層數相關,推算一下就能夠知道第 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...spa

    知道了層數,接下來就好辦多了,這時咱們就知道所求的那點必定在第 t 層這個圈上,順着往下數就是了。要注意的就是螺旋隊列數值增加方向和座標軸正方向並不必定相同。咱們能夠分紅四種狀況——上、下、左、右——或者——東、南、西、北,分別處於四條邊上來分析。簡單說來就是每一圈數字分爲四個區域。orm

    東|右:x == t,隊列增加方向和 y 軸一致,正東方向(y = 0)數值爲 (2t-1)^2 + t,因此 v = (2t-1)^2 + t + yhtm

    南|下:y == t,隊列增加方向和 x 軸相反,正南方向(x = 0)數值爲 (2t-1)^2 + 3t,因此 v = (2t-1)^2 + 3t - xblog

    西|左: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 + xget

    其實還有一點很重要,否則會有大 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;

}

 

 

轉自:http://blog.sina.com.cn/s/blog_4b687eac0100f0oa.html

相關文章
相關標籤/搜索