这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战
第七题:螺旋折线
题目描述
如图p1.pgn所示的螺旋折线经过平面上所有整点恰好一次。
对于整点(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
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。
代码1
暴力求解法
package day_08;
import java.util.Scanner;
public class 螺旋折线 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int i=scanner.nextInt();
int j=scanner.nextInt();
int res=dis(i,j);
System.out.println(res);
}
static int dis(int i,int j) {
int x=0,y=0;
int count=1;
int Left=0,Up=0,Right=0,Down=0;
int num=0;
while(true) {
Left=0;
Up=0;
Right=0;
Down=0;
while(Left<count) {
x--;
Left++;
num++;
if(isXY(x,y,i,j))
return num;
}
while(Up<count) {
y++;
Up++;
num++;
if(isXY(x,y,i,j))
return num;
}
count++;
while(Right<count) {
x++;
Right++;
num++;
if(isXY(x,y,i,j))
return num;
}
while(Down<count) {
y--;
Down++;
num++;
if(isXY(x,y,i,j))
return num;
}
count++;
}
}
static boolean isXY(int x,int y,int i,int j) {
if(i==x&&j==y)
return true;
return false;
}
}
运行这个数据已经有明显的的迟钝,虽然几秒后能得出结果,但x、y等于1000000000 时得不出结果。
代码2
算法优化法
package day_08;
import java.util.Scanner;
import java.math.*;
public class 螺旋折线_算法版 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
long i=scanner.nextLong();
long j=scanner.nextLong();
long res=dis(i,j);
System.out.println(res);
}
static long dis(long i,long j) {
//这个点在竖线上
//我们按1 3 5 7 的递增数列计算
if(Math.abs(i)-Math.abs(j)>=0) {
long m=Math.abs(j-i);
j=i;
if(i<0) {
m-=1;
j=i+1;
}
long n=Math.abs(i+j);
return n*n+m;
}
//这个点在横线上
//我们按2 4 6 8的递增数列
if(Math.abs(i)-Math.abs(j)<0) {
long m=0;
long n=0;
m=Math.abs(j-i);
if(i<0) {
n=(-i)+(-i-1);
}else {
n=2*i;
}
return n*(n+1)+m;
}
return 0;
}
}