1. 程式人生 > >2018藍橋杯省賽Java B 組

2018藍橋杯省賽Java B 組

引言:2018藍橋杯 Java B 個人解析
該題方法很多,就不列舉了。

題目7:螺旋折線

如圖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,否則按無效程式碼處理。
這裡寫圖片描述

我在做的時候首先想到的就是把原圖分為4個象限,不同位置的點使用不同的函式計算。
有個規律,每一圈,左下角的點的值都是所在邊的長度的平方。
例如:dis(-1,0)=1,dis(-2,-1)=9.
下面我給出部分dis值的參照表,方便參考。

座標 dis值
0,0 0
-1,0 1
-1,1 2
0,1 3
1,1 4
1,0 5
1,-1 6
0,-1 7
-1,-1 8
-2,-1 9

這裡寫圖片描述
方法一、
如圖2所示,將折線按顏色分為4個區域,對應的計算函式為left,up,right,down。
左下角點(-3,-2)的值恰為其所在邊長度的平方,也就是(2*(-x)-1)^2。
那麼,該邊上其他點的dis值就是該點到左下角點的距離加上左下角點的值,dis(x,x+1)。
左上角點有其位置的特殊性,座標均為(x,-x),因此其值恰為dis(左下角點)+|x|。
有個距離函式:Point.distance(x1,y1,x2,y2);返回兩點的距離的double值。
其他邊依次類推,上一邊的最後一個點,也是下一邊的第一個點。

import java.awt.Point;
import java.util.Scanner;


public class Main {

    public static int left(int x,int y){

        if((x+1)==y)return(int)(2*(-x)-1)*(2*(-x)-1);//左下角座標,dis(x,y)=(2*(-x)-1)^2
        if(y==-x)return(int) ((2*(-x)-1)*(2*(-x)-1)+Point.distance(x, y, x, x+1));//左上角座標,dis(x,y)=dis(左下角)+point.distance(左下角,左上角);
        //左下角-左上角之間的其他任意點的值等於左下角的值加上該點與左下角的距離
        if(y!=x||y!=-x)         
        return(int) (left(x,x+1)+Point.distance(x, y, x, x+1));
        return 0;

    }
    public static int up(int x,int y){
        if(x==y)return(int) (left(-x,y)+Point.distance(x,y,-x,y));
        if(x!=-y||x!=y)
        return(int) (left(-y,y)+Point.distance(x, y, -y, y));
        return 0;
    }
    public static int right(int x,int y){
        if(y!=x||y!=-x)return (int)(up(x, x)+Point.distance(x, y, x, x));
        return 0;

    }
    public static int down(int x,int y){
        if(x!=-y||x!=y)
        return (int) (right(-y,y)+Point.distance(x, y, -y, y));
        return 0;

    }
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int x=sc.nextInt();
        int y=sc.nextInt();
        int sum=0;
                if(x<0)sum=left(x, y);
                if(y>0)sum=up(x, y);
                if(x>0)sum=right(x, y);
                if(y<0)sum=down(x, y);
        System.out.println(sum);
    }

}

方法二、
這裡寫圖片描述
大致思想為:將折線分為3部分,①:黑線-黃線之間 ②:黃線-紫線之間 ③: 紫線-黑線之間
同方法一所述,區域①部分點的dis值均可基於左下角點計算,即滿足(x,x+1)(x<0)的點。
區域②可基於右上角點減去兩點之間距離計算。左上角點(x==y)的dis值滿足(x+y)^2。
區域③即可通過左下角點和右上角點結合計算。
方法三、
這裡寫圖片描述
大致思想:可將折線分割為多個區域,每種顏色所在的線段的值都是按照一定規律遞增的。

如有錯誤之處,歡迎指出。