上文链接:递增三元组 暴力+动态规划【蓝桥杯真题】(c++实现)
螺旋折线
如图p1.png所示的螺旋折线经过平面上所有整点恰好一次。
对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度。
例如dis(0, 1)=3, dis(-2, -1)=9
给出整点坐标(X, Y),你能计算出dis(X, Y)吗?
【输入格式】
X和Y
对于40%的数据,-1000 <= X, Y <= 1000
对于70%的数据,-100000 <= X, Y <= 100000
对于100%的数据, -1000000000 <= X, Y <= 1000000000
【输出格式】
输出dis(X, Y)
【样例输入】
0 1
【样例输出】
3
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
思路分析
- 该题求某坐标在螺旋折线中距原点的长度,有上述图片可以看出规律:
螺旋折线可以拆分成一个个正方形,正方形的边长按照2、4、6、8的等差数列排列,每个正方形里面分布多个坐标点,寻找规律如下:
(1)对于满足y<x和-y<=x的点,
如果x>0,则长度sum = 前(x的绝对值 -1)个正方形的周长和 + 2 (2乘 x) +(x - y);
如果x<0,则长度sum = 前(x的绝对值 -1)个正方形的周长和 + (- x + y)
(2)对于满足y>=x和-y>x的点,
如果 y>0,则长度sum = 前(y的绝对值 -1)个正方形的周长和 + 2 * y+ (y + x);
如果y<0,则长度sum = 前(y的绝对值 -1)个正方形的周长和 + 3(2乘 y的绝对值) + (- y - x)
- 注意点:需明白上述图中两个黑箭头将区间分为了四份。
算法展示
#include <iostream>
using namespace std;
#include <algorithm>
int main()
{
int x,y;
cin>>x>>y;
long long sum = 0;
if((y<x)&&(-y<=x))
{
sum+=x>1?(long long)(4*(2+(abs(x)-1)*(abs(x)-2))):0;//求前n个正方形周长的等差数列和
sum+=(long long)x>0?(4*x+(x-y)):(y-x);
}
else
{
sum+=y>1?(long long)(4*(2+(abs(y)-1)*(abs(y)-2))):0;//求前n个正方形周长的等差数列和
sum+=(long long)y>0?(2*y+y+x):(6*y-y-x);
}
cout<<sum<<endl;
return 0;
}