【编程马拉松算法目录>>>】
【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