搜狗2018校园招聘编程题学习

圆周上两点间的距离

时间限制:C/C++语言 1000MS;其他语言 3000MS
内存限制:C/C++语言 30720KB;其他语言 555008KB
题目描述:
定义圆周上两点的距离s为这两点之间的劣弧对应的圆心角度数(0<=s<=180),现输入圆周上的n个点(n>=2),以角度a表示其位置(0<=a<360),输入按a从小到大排序。求最远的一对点之间的距离。
输入
第一行为点个数n,后跟n行,每行一个双精度浮点数,表示点的角度(小数点后保留8位),例如输入样例中为4个点的输入:
输出
输出最远的一对点之间的距离(双精度浮点数,小数点后保留8位)和'\n'换行符。例如输入样例中,10.00000000与183.00000000两个点之间的距离为173.00000000,大于10.00000000与198.0000000之间的距离172.00000000,所以应输出:
173.00000000

样例输入
4
10.00000000
180.00000000
183.00000000
198.00000000
样例输出
173.00000000

Hint
注意事项:
1.程序性能要足够快,否则可能无法通过一些大型测试数据;
2.如果使用java语言,可以考虑使用BufferedReader从标准输入读取输入数据,Scanner读取一些比较大的输入数据会发生超时。
思路:题目意思很简单,给你圆上一些点,求圆上两个点的最大距离。注意:由于是劣弧,所以所得到的圆心角度数<=180。如果所求的距离x大于180就等于(360-x)。

暴力求解:很简单就是两个for循环遍历,依次求两个点中的最大距离。但是这个代码只能通过50%。本来以为是Scanner的原因,换位BufferedReader后结果还是50%这个情况。猜想:可能是两个for循环嵌套复杂度变大了,要对代码进行局部优化,使其变为一个for循环或者一个while。

import java.util.Scanner;

public class Test {
	public static void main(String[] args){
		Scanner sr = new Scanner(System.in);
		int n=sr.nextInt();
		Double f[]=new Double[n];
		for(int i=0;i<n;i++){
			f[i]=sr.nextDouble();
		}
		
		Double max=Double.MIN_VALUE;
		for(int i=0;i<n;i++){
			for(int j=i+1;j<n;j++){
				//dif即为两个点的圆形角差距
				Double dif=Math.abs(f[i]-f[j]);
				//大于180那么就取360-dif
				if(dif>180){
					dif=360-dif;
				}
				if(dif>max){
					max=dif;
				}
			}
		}
		//max即为最大距离,用String的format方法转成小数点后保留8位输出。
		System.out.println(String.format("%.8f",max));
	}
}

优化后代码:整体思想就是以圆上两个点组成的半圆慢慢移动,始终让差值接近180。

  1. 让big指针先移动,直到big所指向的值与samll所指向的值大于180。(同时将期间的最大值赋给max),然后samll开始移动。
  2. samll开始移动,同时判断它和samll所指向的值差值是否小于180,一旦小于180则big又开始移动。
  3. 如此反复,直到big>=n。最后输出max的值。微笑
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test {

    public static void main(String args[]) throws IOException {
        InputStreamReader in = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(in);
        int n = Integer.valueOf(br.readLine());
        double[] f = new double[n];
        for (int i = 0; i < n; i++) {
            f[i] = Double.valueOf(br.readLine());
        }
        
        double max = 0.0;	//圆上两点最后输出的最大距离
        int samll = 0;		//开始指针
        int big = 1;		//跟进指针

        while(big < n){
        	//定义两点距离diff
            double diff = f[big] - f[samll];
            //如果diff超过180
            if(Double.compare(diff , 180.0) > 0){
                double dif = Math.abs(f[big] - f[samll]);
                //dif大于180就取(360-dif),反之则取dif
                double dist=360.0 - dif; 
                //如果测试的两个点的距离大于max则将dist赋给max。同时small往后移动
                if(dist > max)
                    max = dist;
                samll++;
            }else{
            	//diff大于max则big往后移,(刚开始是一直往后移,直到大于180为止)
                if(diff > max)
                max = diff;
                big++;
            }
        }
        System.out.printf("%.8f\n" , max);
    }
}




  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值