【编程马拉松】【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 解题思路



  题目中输入的数值比较大,所以不能使用一般的字数字进行计算,要使用大整数乘法思想。

  假设猫的长度是m(m=xi?1xi?2…x0),碗的半径是n(n=xj?1xj?2…x0),π取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上进行【下载>>>】

时间: 2024-10-19 06:19:44

【编程马拉松】【008-快到碗里来】的相关文章

【编程马拉松】【006-统计一】

[编程马拉松算法目录>>>] [006-统计一][工程下载>>>] 1 题目描述 NewCode总是力争上游,凡事都要拿第一,所以他对"1"这个数情有独钟.爱屋及乌,他也很喜欢包含1的数,例如10.11.12.--. 例如:N=2,1.2出现了1个"1".N=12,1.2.3.4.5.6.7.8.9.10.11.12.出现了5个"1".你能帮他统计一下整数里有多少个1吗? 1.1 输入描述: 输入有多组数据,每

【编程马拉松】【026-是男人就下100层】

[编程马拉松算法目录] [026-是男人就下100层][工程下载>>>] 1 题目描述 相信大家都听说过"是男人就下100层"系列游戏,游戏中包括多个长度和高度各不相同的平台,地面是最低的平台,高度为零,长度无限. 一个男人在开始的时候从高于所有平台的某处开始下落,它的下落速度始终为1米/秒.当他落到某个平台上时,游戏者选择让他向左或向右跑,跑动的速度也是1米/秒.当他跑到平台的边缘时会继续下落.要求每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束. 请帮忙

hdu 4542 数论 + 约数个数相关 腾讯编程马拉松复赛

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4542 小明系列故事--未知剩余系 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 889    Accepted Submission(s): 207 Problem Description "今有物不知其数,三三数之有二,五五数之有三,七七数之有

HDU 4508 湫湫系列故事——减肥记I (2013腾讯编程马拉松初赛第一场)

http://acm.hdu.edu.cn/showproblem.php?pid=4508 题目大意: 给定一些数据. 每组数据以一个整数n开始,表示每天的食物清单有n种食物. 接下来n行,每行两个整数a和b,其中a表示这种食物可以带给湫湫的幸福值(数值越大,越幸福),b表示湫湫吃这种食物会吸收的卡路里量. 最后是一个整数m,表示湫湫一天吸收的卡路里不能超过m. 思路: 完全背包. 一开始以为是01背包. 敲了01后样例2不对啊!!! 然后改成完全就过了..就改循环体就好了.. #includ

【编程马拉松】【027-最短编辑距离】

[编程马拉松算法目录] [027-最短编辑距离][工程下载>>>] 1 题目描述 1.1 输入描述: UNIX系统下有一个行编辑器ed,它每次只对一行文本做删除一个字符.插入一个字符或替换一个字符三种操作.例如某一行的内容是"ABC",经过把第二个字符替换成"D".删除第一个字符.末尾插入一个字符"B",这三步操作后,内容就变成了"DCB".即"ABC"变成"DCB"需

程序员如何做到『编程速度又快,Bug 数量又少』?

有网友在 Quora 提问:如何把自己训练得『编程速度又快,Bug 数量又少』?下面是 Glyn Williams 的回复很精彩,4.5 k 赞. 三个程序员被要求穿过一片田地,到达另一侧的房子. 菜鸟程序员目测了一下之间很短的距离,说:"不远!我只要十分钟." 资深程序员看了一眼田地,想了一会,说:"我应该能在一天内过去."菜鸟程序员很惊讶. 大神程序员看了一眼田地,说:"看起来要十分钟,但我觉得十五分钟应该够了." 资深程序员冷笑了一声. 菜

【编程马拉松】【024-放苹果】

[编程马拉松算法目录] [024-放苹果][工程下载>>>] 1 题目描述 把 M 个同样的苹果放在 N 个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法? 注意:5.1.1 和 1.5.1 是同一种分法,即顺序无关. 1.1 输入描述: 输入包含多组数据. 每组数据包含两个正整数 m和n(1≤m, n≤20). 1.2 输出描述: 对应每组数据,输出一个整数k,表示有k种不同的分法. 1.3 输入例子: 7 3 1.4 输出例子: 8 2 解题思路 2.1 解法一 放苹果,

【编程马拉松】【021-数据库连接池】

[编程马拉松算法目录] [021-数据库连接池][工程下载>>>] 1 题目描述 Web系统通常会频繁地访问数据库,如果每次访问都创建新连接,性能会很差.为了提高性能,架构师决定复用已经创建的连接.当收到请求,并且连接池中没有剩余可用的连接时,系统会创建一个新连接,当请求处理完成时该连接会被放入连接池中,供后续请求使用. 现在提供你处理请求的日志,请你分析一下连接池最多需要创建多少个连接. 1.1 输入描述: 输入包含多组数据,每组数据第一行包含一个正整数n(1≤n≤1000),表示请求

【编程马拉松】【019-一笔画】

[编程马拉松算法目录] [019-一笔画][工程下载>>>] 1 题目描述 咱们来玩一笔画游戏吧,规则是这样的:有一个连通的图,能否找到一个恰好包含了所有的边,并且没有重复的路径. 1.1 输入描述: 输入包含多组数据.每组数据的第一行包含两个整数n和m (2≤n, m≤1000),其中n是顶点的个数,m是边的条数.紧接着有m行,每行包含两个整数from和to (1 ≤ from, to ≤ n, from != to),分别代表边的两端顶点.边是双向的,并且两个顶点之间可能不止一条边.