螺旋队列,数字排序就是这样以下图这样的螺旋排列,细心看后会发现数字是以顺时针的旋转递增,每圈的最大数字是红色圈圈匡住的数字,设1的坐标是(0,0,)为原点方向,按常理逻辑以上为y轴的正方向,以右为x轴的正方向,以数10的坐标为(2,1),数20的坐标为(-2,1),数22的坐标为(-1,2),数16的坐标为(-1,-2)为例子,我们可以发现:
从0层的1,到1层的9,到2层的25,到2层的49。可以看出这是连续奇数的和:1,3,5...的平方,可以推论出以后的第t层有(t*2+1)平方个数,也是此层最大值。
给定一对坐标(x,y)。 如何确定该点处于第几层?我们可以这样判断:c = max(abs(x),abs(y));
根据例子我们可以推论出:
- x == c 时,右方向的数10例子,我们可以推论出值和max ,x,y的关系为:max+(-7*x-y)
- x == -c时,左方向的数20例子,我们同样可以推论出:max+(3*x+y)
- y == c 时,上方向的数22例子,我们同样可以推论出:max+(x-y)
- y == -c时,下方向的数16例子,我们同样可以推论出:max+(-x+5y)
其实是有一点很重要,不然会有问题。其他三边还好,但是在右边那条线上,队列增加不完全符合公式,右上角是本层的最后一个数,再往下却是本层的第一个数,不满足右线公式,所以我们可以把右线的判断放在最后(其实只需要放在上线之后就可以了),这样一来,右上角的那点始终会被认为是上线的点。
代码如下:
int spiral(int x,int y)
{
int c = max(abs(x),abs(y)); //当前坐标所在圈
int max = (2*c+1)*(2*c+1);
if(y == -c)//下边
return max+(5*y-x);
else if(x==-c) //左边
return max+(3*x+y);
else if(y == c)//上边
return max+(x-y);
else //右边
return max+(-x*7-y);
}
int main()
{
int x,y;
cin >> x >> y;
cout << spiral(x,y) << endl;
}