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

Posted Wang-Junchao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编程马拉松008-快到碗里来相关的知识,希望对你有一定的参考价值。

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


【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=xi1xi2x0 ,碗的半径是 nn=xj1xj2x0 ,π取3.14。只要比较n和2*m*π的大小就可以判断猫是否可以进入碗里。因为m、n不能使用数字来表示,可以使用数组a、b来表示他们。同时因为π是小数,要将m、n、π统一成整数进行运算。可以将m放大100倍,π放大100倍。a[0]=0,a[1]=0,表示放大100倍,a[k]表示m中的 xk2 ,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-快到碗里来的主要内容,如果未能解决你的问题,请参考以下文章

Offer快到碗里来—聊聊线程池

Android探索之旅(第三十一篇)你想要的工具类集合都在这里,快到碗里来

.NET Offer 快到碗里来!.NET 招聘季

每日一题 | day26(变态跳台阶 | 快到碗里来)

10000+ gif表情包不是梦,get这一篇文就够了!!!小哥哥快到碗里来,再也不怕斗图没有表情包了

老男孩双11课程首次最高优惠4000元,还不快到碗里来?