前言
读者们你们好! 接下来你们将看到我关于POJ 3299 Humidex这道题的理解。博主我是从这一题才正式开始学习算法的,所以耗费了很长时间(将近一天)才最终完成,过程中对于题目和Java编程的一些问题有所感悟,所以决定记录下来,以便后续的改进和反省,并将结果分享给大家。
题目
本道题来自北京大学的POJ系统,题号3299,题名Humidex。
链接: POJ3299
对于题目的理解
这道题本身不难,其要求就是:在Temperature, Dewpoint和Humidex这三个变量中,任意已知其中两个变量的前提下求出第三个变量,最后按统一格式输出,题目中已经详细给了计算公式:
humidex = temperature + h
h = (0.5555)× (e - 10.0)
e = 6.11 × exp [5417.7530 × ((1/273.16) - (1/(dewpoint+273.16)))]
where exp(x) is 2.718281828 raised to the exponent x.
从算法角度来说,这道题没有难度,在许多刷题推荐帖上也被列为水题之一,接下来我从一个第一次接触POJ的人的角度来讲讲要注意的事项:
- 对于题目的理解一定要准确,我第一次就是只看了题目一遍,然后就去看输入输出的范例了,结果写出来的代码就只能针对范例给的那一种情况,提交也老是被判WrongAnswer,后来又仔细看了一遍题目才知道是要在三个变量中给二求一的,所以大家看题目一定要仔细。
- 代码的输出一定要处理得和范例给的一摸一样,小数点,字母的顺序等都要完全一致,不然是不会被系统通过的。
- 以上是对小白所讲的注意事项,老生大可不必阅读。
代码
以下是博主第一次通过系统判断的代码,尚未做任何优化,仅此记录一下,大家可自行修改,博主后续也会再优化的。
注意事项
对于没有接触过ACM模式的人来说,写代码时最大的困难大概就是要处理多行输入的问题,博主一开始也在这块花了不少时间。
题目的输入输出范例
Sample Input:
T 30 D 15
T 30.0 D 25.0
E
Sample Output:
T 30.0 D 15.0 H 34.0
T 30.0 D 25.0 H 42.3
源代码
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
private static final double EXP = 2.718281828;
//已知humidex和dewpoint求temperature
public static double sloveHD(double hex, double dep) {
BigDecimal exp1 = new BigDecimal("1").divide(new BigDecimal("273.16"), 12, RoundingMode.HALF_UP).subtract(new BigDecimal("1").divide(new BigDecimal(Double.toString(dep)).add(new BigDecimal("273.16")), 12, RoundingMode.UP));
BigDecimal exp2 = new BigDecimal("5417.7530").multiply(exp1);
double e = 6.11 * Math.pow(EXP, exp2.setScale(12, RoundingMode.HALF_UP).doubleValue());
double h = 0.5555 * (e - 10.0);
String result = Double.toString(hex - h);
BigDecimal tem = new BigDecimal(result).setScale(1, RoundingMode.HALF_UP);
return tem.doubleValue();
}
//已知humidex和temperature求dewpoint
public static double sloveHT(double hex, double tem) {
double h = hex - tem;
double e = h / 0.5555 + 10.0;
double dep = -(Math.log(e / 6.11) / 5417.7530) * 273.16 * 273.16 / (273.16 * (Math.log(e / 6.11) / 5417.7530) - 1);
BigDecimal result = new BigDecimal(dep).setScale(1, RoundingMode.HALF_UP);
return result.doubleValue();
}
//已知dewpoint和temperature求humidex
public static double sloveTD(double tem, double dep) {
BigDecimal exp1 = new BigDecimal("1").divide(new BigDecimal("273.16"), 12, RoundingMode.HALF_UP).subtract(new BigDecimal("1").divide(new BigDecimal(Double.toString(dep)).add(new BigDecimal("273.16")), 12, RoundingMode.UP));
BigDecimal exp2 = new BigDecimal("5417.7530").multiply(exp1);
double e = 6.11 * Math.pow(EXP, exp2.setScale(3, RoundingMode.HALF_UP).doubleValue());
double h = 0.5555 * (e - 10.0);
String result = Double.toString(new BigDecimal(Double.toString(tem)).doubleValue() + h);
BigDecimal hex = new BigDecimal(result).setScale(1, RoundingMode.HALF_UP);
return hex.doubleValue();
}
public static void getHex(String inPut) {
String[] in = inPut.trim().split(" ");
String nameOne = in[0];
BigDecimal argOne = new BigDecimal(in[1]).setScale(1, RoundingMode.HALF_UP);
String nameSecond = in[2];
BigDecimal argSecond = new BigDecimal(in[3]).setScale(1, RoundingMode.HALF_UP);
double hex;
double tem;
double dep;
if ("H".equals(nameOne)) {
if ("D".equals(nameSecond)) {
hex = argOne.doubleValue();
dep = argSecond.doubleValue();
tem = sloveHD(hex, dep);
System.out.println("T" + " " + tem + " " + nameSecond + " " + argSecond + " " + nameOne + " " + argOne);
} else if ("T".equals(nameSecond)) {
hex = argOne.doubleValue();
tem = argSecond.doubleValue();
dep = sloveHT(hex, tem);
System.out.println(nameSecond + " " + argSecond + " " + "D" + " " + dep + " " + nameOne + " " + argOne);
}
} else if ("T".equals(nameOne)) {
if ("H".equals(nameSecond)) {
tem = argOne.doubleValue();
hex = argSecond.doubleValue();
dep = sloveHT(hex, tem);
System.out.println(nameOne + " " + argOne + " " + "D" + " " + dep + " " + nameSecond + " " + argSecond);
} else if ("D".equals(nameSecond)) {
tem = argOne.doubleValue();
dep = argSecond.doubleValue();
hex = sloveTD(tem, dep);
System.out.println(nameOne + " " + argOne + " " + nameSecond + " " + argSecond + " " + "H" + " " + hex);
}
} else if ("D".equals(nameOne)) {
if ("H".equals(nameSecond)) {
dep = argOne.doubleValue();
hex = argSecond.doubleValue();
tem = sloveHD(hex, dep);
System.out.println("T" + " " + tem + " " + nameOne + " " + argOne + " " + nameSecond + " " + argSecond);
} else if ("T".equals(nameSecond)) {
dep = argOne.doubleValue();
tem = argSecond.doubleValue();
hex = sloveTD(tem, dep);
System.out.println(nameSecond + " " + argSecond + " " + nameOne + " " + argOne + " " + "H" + " " + hex);
}
}
}
public static void main(String[] args) {
try {
//处理输入
Scanner in = new Scanner(System.in);
String str = "";
List allInput = new ArrayList();
while (!"E".equals(str)) {
str = in.nextLine();
allInput.add(str);
}
allInput.remove(allInput.size() - 1);
for (Object item : allInput) {
getHex((String) item);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果
耗时了将近一天,虽然题目简单,但是过程艰难,最后成功了,对于我这个小白来说,还是很开心的啊!
后记
后期博主还会对代码进行优化,欢迎大家指出不足,希望我们都能在算法这条路上走得更远,共勉!
问题
记录一些在写代码过程中遇到的问题:
- 使用new BigDecimal(double val)要极其注意,有可能产生不可预知的后果,相关帖子可以参考:链接
- 平常使用的JDK一般是JDK8,POJ使用的JDK5,大家在编写的时候要注意,特别是关于泛型的方面。