旋轉(zhuǎn)隊列的簡要分析
題目大概如下所示:
設1點的坐標是(0,0),x方向向右為正,y方向向下為正。例如:7的坐標為(-1,-1),2的坐標為(1,0),3的坐標為(1,1)。編程實現(xiàn)輸入任意一點坐標(x,y),輸出所對應的數(shù)字;或輸入任意數(shù)字,輸出該數(shù)字的坐標。實現(xiàn)的效果如上圖所示,從圖中可知,只需要找到正確的數(shù)值分析式,就能夠得到坐標處對應的數(shù)值。
下面簡要的分析其中的一些規(guī)律,這類問題我覺得關鍵還是要找到突破點,然后找到具體數(shù)值的表達式,表達式清楚了就只是程序的轉(zhuǎn)化問題啦。
從圖上可知,在第0層時只有一個值1,第1層是有8個值(2-9),第2層上的值從10到25,第3層的值從26到49,由圖可知每一層的最后一個值都是奇數(shù)的平方(1,9,25,49,81,...),再和層數(shù)關聯(lián)起來,得到每一層的最后一個數(shù)都是(2n+1)^2,同樣每一層的起始值也就可以確定,即(2n-1)^2+1。也就是每一層的值都是處在(2n-1)^2+1和(2n+1)^2之間,這樣采用(2n-1)^2作為一個基準,加上對應的數(shù)就能得到具體的數(shù)值。
因此我們可以得到如下的結論:
旋轉(zhuǎn)隊列每一層的開始值都是(2n-1)^2+1,結尾值都是(2n+1)^2,其中的n就是層數(shù)(0,1,2,...),可以認為是坐標中較大的絕對值值確定所在的層,比如(2,3),則表示該坐標處于第3層,而(-3,-2)也表示這個數(shù)值在第3層上。有了這種層的概念就會使得推理的過程更見的簡單。也就是說坐標值中絕對值較大的值就是所謂的層。
結合上面的圖像可知道,每一層的開始值都是出于東方,也就是x>0的方向,結束于北方,即y<0的方向,這時候我們可以根據(jù)東西南北四個方向來確定坐標對應的值。
即:首先采用輸入的坐標值確定該數(shù)值對應的層數(shù),然后根據(jù)輸入坐標的x,y確定坐標所在的方向,這時候依據(jù)每一個方向的起始值就能較好的確定所有的值(具體分析該值與每一層的開始值之間的聯(lián)系),但是這種方法有問題,因為每一層上每個方向(東西南北)的起始坐標都是在變化的,并不便于得到通用的表達式。
這時候可以考慮對稱性問題,因為在上面的圖中我們可以知道該圖基本上是按照x,y對稱的,如果我們知道了四個正方向的值,那么就能根據(jù)對稱性快速的確定其他的值,也就是只需要知道每一層與坐標軸相交的幾個值就能快速的確定其他的值。
但是如何讓確定坐標軸上的值呢?
這就要密切聯(lián)系每一層的結束值(2n+1)^2,根據(jù)這個值我們可以知道下一層正東方的值(2n+1)^2+n+1,加入坐標所在的層為K,則正東方的值就應該是(2*K-1)^2+K,這個可以很容易的確定,因為開始值到坐標軸的距離剛好就是層數(shù)K,也就是加上K。其他三個方向的值也就能夠快速的確定。
因此我們可以知道每一個方向的對稱軸的表達式分別為:
正東方:(2*K-1)^2+K
正南方:(2*K-1)^2+3K
正西方:(2*K-1)^2+5K
正北方:(2*K-1)^2+7K
依據(jù)每一個方向的坐標軸的對稱性確定對應的值,在對稱的方向上只需要一個坐標值就能確定其他的值,這時候四個方向上的值分別為:
東方:(2*K-1)^2 + K + y
南方:(2*K-1)^2 + 3K - x
西方:(2*K-1)^2 + 5K - y
北方:(2*K-1)^2 + 7K + x
這樣也就找到了每一行的表達式,就能實現(xiàn)每一個方向上數(shù)值的確定。程序的實現(xiàn)也就相對來說非常容易實現(xiàn)啦。在打印的過程中需要注意數(shù)組行列的差別。
實現(xiàn)的基本過程如下:
#include
#include
using namespacestd;
#define abs(x) ((x) > 0 ? (x) : (-x))
#define max(x,y) (abs(x) >= abs(y) ? abs(x) : abs(y))
int reverse_xy(int x, int y)
{
int cnt = 0;
/*保存所在的行*/
int t = max(x, y);
/*最先判斷北方(y=-t)*/
if(-t == y)
{
cnt = (2*t-1)*(2*t-1) + 7*t + x;
}
else if(-t == x)/*西方*/
{
cnt = (2*t-1)*(2*t-1) + 5*t - y;
}
else if(t == y)/*南方*/
{
cnt = (2*t-1)*(2*t-1) + 3*t - x;
}
else if(t == x)/*東方*/
{
cnt = (2*t-1)*(2*t-1) + t + y;
}
return cnt;
}
int main()
{
int array[9][9] = {0};
int x = 0;
int y = 0;
for(y = 0; y <= 8 ; ++ y)
{
for(x = 0; x <= 8; ++ x)
{
array[x][y] = reverse_xy(x-4 , y-4);
cout << array[x][y] << " ";
}
cout << endl;
}
}
評論