码迷,mamicode.com
首页 > 其他好文 > 详细

【编程马拉松】【008-快到碗里来】

时间:2016-06-08 10:45:33      阅读:255      评论:0      收藏:0      [点我收藏+]

标签:

【编程马拉松算法目录>>>】


【008-快到碗里来】【工程下载>>>】


1 题目描述


  小喵们很喜欢把自己装进容器里的(例如碗),但是要是碗的周长比喵的身长还短,它们就进不去了。现在告诉你它们的身长,和碗的半径,请判断一下能否到碗里去。

1.1 输入描述:


  输入有多组数据。每组数据包含两个整数n (1≤n≤2^128) 和r (1≤r≤2^128),分别代表喵的身长和碗的半径。圆周率使用3.14。

1.2 输出描述:


  对应每一组数据,如果喵能装进碗里就输出“Yes”;否则输出“No”。

1.3 输入例子:


6 1
7 1
9876543210 1234567890

1.4 输出例子:


Yes
No
No

2 解题思路


  题目中输入的数值比较大,所以不能使用一般的字数字进行计算,要使用大整数乘法思想。
  假设猫的长度是mm=xi?1xi?2x0,碗的半径是nn=xj?1xj?2x0,π取3.14。只要比较n和2*m*π的大小就可以判断猫是否可以进入碗里。因为m、n不能使用数字来表示,可以使用数组a、b来表示他们。同时因为π是小数,要将m、n、π统一成整数进行运算。可以将m放大100倍,π放大100倍。a[0]=0,a[1]=0,表示放大100倍,a[k]表示m中的xk?2,b[k]表示n中的xk。π使用数组PI表示。PI[0]=4,PI[1]=1,PI[2]=3。计算2*b*PI(结果为r)再比较r与n的大小即可。

3 算法实现


import java.util.Scanner;

/**
 * Author: 王俊超
 * Time: 2016-05-09 08:44
 * CSDN: http://blog.csdn.net/derrantcm
 * Github: https://github.com/Wang-Jun-Chao
 * Declaration: All Rights Reserved !!!
 */
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
//        Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data.txt"));
        while (scanner.hasNext()) {
            String cat = scanner.next();
            String bowl = scanner.next();
            System.out.println(toTheBowl(cat, bowl));
        }

        scanner.close();
    }

    /**
     * 判断猫是否可以进到碗里
     *
     * @param cat  猫的长度
     * @param bowl 碗的半径
     * @return Yes:猫可以到碗里,false:猫不可以到碗里
     */
    private static String toTheBowl(String cat, String bowl) {

        // 200*PI
        int[] PI = {8, 2, 6};
        // cat的值要放大100倍
        int[] n = new int[cat.length() + 2];
        int[] m = new int[bowl.length()];
        // 将cat转换成数值,并且放大100倍
        for (int i = 0; i < cat.length(); i++) {
            n[i + 2] = cat.charAt(cat.length() - i - 1) - ‘0‘;
        }

        // bowl转换成数值
        for (int i = 0; i < bowl.length(); i++) {
            m[i] = bowl.charAt(bowl.length() - i - 1) - ‘0‘;
        }

        int[] r = calculate(m, PI);

        if (compare(r, n) >= 0) {
            return "Yes";
        } else {
            return "No";
        }
    }

    /**
     * 比较两个整数是否相等,下标由小到大表示由低位到高位,忽略最高有效位上的前导0
     *
     * @param m 整数
     * @param n 整数
     * @return m > n返回1,m = n返回0,m < n返回-1
     */
    private static int compare(int[] m, int[] n) {

        if (m == null && n == null) {
            return 0;
        }
        // null最小
        if (m == null) {
            return -1;
        }

        if (n == null) {
            return 1;
        }

        int lastM = m.length - 1;
        int lastN = n.length - 1;

        // 找m的最高有效位的位置,至少有一位
        while (lastM >= 1 && m[lastM] == 0) {
            lastM--;
        }
        // 找n的最高有效位的位置,至少有一位
        while (lastN >= 1 && n[lastN] == 0) {
            lastN--;
        }

        // m的数位比n多,说明m比n大
        if (lastM > lastN) {
            return 1;
        }
        // m的数位比n少,说明m比n小
        else if (lastM < lastN) {
            return -1;
        } else {
            // 位数一样,比较每一个数位上的值,从高位到低位进行比较
            for (int i = lastM; i >= 0; i--) {
                if (m[i] > n[i]) {
                    return 1;
                } else if (m[i] < n[i]) {
                    return -1;
                }
            }

            return 0;
        }
    }

    /**
     * 两个数相乘
     *
     * @param m 乘数
     * @param n 乘数
     * @return 结果
     */
    private static int[] calculate(int[] m, int[] n) {

        if (n == null || n.length < 1 || m == null || m.length < 1) {
            return null;
        }

        // 结果最多的位数
        int[] r = new int[m.length + n.length];
        // 来自低位的进位
        int c;

        int t;
        int k;

        for (int i = 0; i < n.length; i++) {
            // 计算n[i]*m

            if (n[i] == 0) {
                continue;
            }

            c = 0;
            for (int j = 0; j < m.length; j++) {
                t = n[i] * m[j] + r[i + j] + c;
                r[i + j] = t % 10;
                c = t / 10;

            }

            // 如果还有进位要继续处理
            k = i + m.length;
            while (c != 0) {
                t = c + r[k];
                r[k] = t % 10;
                c = t / 10;
                k++;
            }
        }

        return r;
    }
}

4 测试结果


技术分享

5 其它信息


因为markddow不好编辑,因此将文档的图片上传以供阅读。Pdf和Word文档可以在Github上进行【下载>>>】

【编程马拉松】【008-快到碗里来】

标签:

原文地址:http://blog.csdn.net/derrantcm/article/details/51610940

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!