2018年第九届蓝桥杯省赛-螺旋折线

137 阅读1分钟

这是我参与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,否则按无效代码处理。

image.png

代码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;
	}
}

image.png

运行这个数据已经有明显的的迟钝,虽然几秒后能得出结果,但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;

	}
}