题目:
如图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
分析:
这道题我知道一定是找规律,但是我想了半天也没有什么头绪,于是我决定用深搜来做,但是后面的案例超内存了,最后只得了50%的分
代码:
#include<iostream>
#include<cmath>
using namespace std;
int xf,yf;
void dfs(int x,int y,int cnt){
if(x == xf && y== yf){
cout << cnt;
exit(0);
}
if(y <= 0 && x - y >= 0 && abs(x) <= abs(y)){//向左走
dfs(x-1,y,cnt+1);
}
if(x < 0 && x + y < 0 && abs(y) < abs(x)){//向上走
dfs(x,y+1,cnt+1);
}
if(y > 0 && x - y < 0 && abs(x) <= y){//向右走
dfs(x+1,y,cnt+1);
}
if(x > 0 && x + y > 0 && abs(y) <= x){//向下走
dfs(x,y-1,cnt+1);
}
}
int main(){
cin >> xf >> yf;
dfs(0,0,0);
return 0;
}
之后借鉴了别人的想法:
打开之后发现是一层层的正方形,且周长构成等差数列
a(1) = 8,a(2) = 16,a(3) = 32……
通过x=y这条直线将所有的点分为两半边:
x>=y
x<y
首先将x==y这条线上的点的规律找出:
(1,1) = 2+2 = 4
(2,2) = 8+4+4 = 16
(3,3) = 8+16+6+6 = 36
==>(x,y) = S(x-1) + 4*x
(-1,-1) = 8
(-2,-2) = 8+16
(-3,-3) = 8+16+24
==> (x,y) = S(abs(x))
接下来将 x>y这半边的点的规律找出:
n = max(abs(x),abs(y))
(x,y) = S(n) - (x+n) - (y+n)
然后是x<y这半边的点的规律:
n = max(abs(x),abs(y))
(x,y) = S(n-1) + 4*n - (n-x) - (n-y)
代码:
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
long long sum(long long n){
return 4*n*n+4*n;
}
int main(){
long long x,y;
cin >> x >> y;
long long m = max(abs(x),abs(y));
if(x > y || (x == y && x <= 0)){
cout << sum(m) - (x+m) - (y+m);
}else if(x < y || (x == y && x > 0)){
cout << sum(m-1) + 4*m - (m-x) - (m-y);
}
return 0;
}