问题描述:
对于如下图所示的图形,该螺旋折线经过平面上所有整点恰好一次。
对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度。
例如dis(0, 1)=3, dis(-2, -1)=9
给出整点坐标(X, Y),你能计算出dis(X, Y)吗?
分析:
这个图形是有规律而循的,只需要找到它的规律,便可以解决类似问题。这类问题也是在编程时最喜欢遇到的问题,言简意赅,所求明确,找出规律,列出通式,由特殊到一般。
由该图可以看出两个坐标轴上的整点是特殊点,寻找规律,列出通式,很容易解决问题。而且都是整点,也就是坐标都是整数,有正有负,但是没有浮点数,比较简单。
1以y轴为参考点
当y >= 0 时:
首先找出几个特殊点:
dis(0,0) = 0;
dis(0,1) = 1 + 1 + 1;
dis(1,1) = 1 + 1 + 1 +1;
dis(0,2) = 1 + 1 + 2 + 2 + 3 + 3 + 2;
dis(2,2) = 1 + 1 + 2 + 2 + 3 + 3 + 2 + 2;
dis(0,3) = 1 + 1 + 2 + 2 + 3 + 3 + 4 + 4 + 5 + 5 + 3;
dis(3,3) = 1 + 1 + 2 + 2 + 3 + 3 + 4 + 4 + 5 + 5 + 3 + 3;
(其余式子也是这个规律)
规律为 两个以2y - 1为通式的等差数列的前n项和再加上y再加X;
即dis = (2 * y) * (2 * y - 1) + y + x;
当y < 0 时:
同理可得:
dis(0,-1) = 1 + 1 + 2 + 2 + 1;
dis(-1,-1) = 1 + 1 + 2 + 2 + 1 - (-1);
dis(0,-2) = 1 + 1 + 2 + 2 + 3 + 3 + 4 + 4 + 2;
dis(-2,-2) = 1 + 1 + 2 + 2 + 3 + 3 + 4 + 4 + 2 - (-2);
dis(0,-3) = 1 + 1 + 2 + 2 + 3 + 3 + 4 + 4 + 5 + 5 + 6 + 6 + 3;
dis(-3,-3) = 1 + 1 + 2 + 2 + 3 + 3 + 4 + 4 + 5 + 5 + 6 + 6 + 3 - (-3) ;
首先对y取绝对值,dis为两个以2|y|为通式的等差数列前n项和再加上|y|减去x;
即:dis = (2 * y) * (2 * y + 1) + y - x;
以x轴为参考点:
以x轴为参考点也是通过找几个点找出其存在的规律,当以x轴为参考点时也要考虑y的正负,分情况讨论。
在此不讨论这种情况。
代码:
#include<iostream>
#include<cmath>
using namespace std;
int dis(int x, int y) //以y轴上的点为关键点
{
int dis; //距离
if (y >= 0) //从(0,0)点开始
{
dis = (2 * y) * (2 * y - 1) + y + x;
}
else
{
y = abs(y); //绝对值
dis = (2 * y) * (2 * y + 1) + y - x;
}
return dis;
}
int main()
{
int x, y;
cin >> x;
cin >> y;
cout << dis(x, y) << endl;
return 0;
}