您的位置:首页 > 编程语言

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

2016-06-08 09:36 204 查看

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

【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)m(m=x_{i-1} x_{i-2}…x_0),碗的半径是n(n=xj−1xj−2…x0)n(n=x_{j-1} x_{j-2}…x_0),π取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−2x_{k-2},b[k]表示n中的xkx_k。π使用数组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上进行【下载>>>】
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: