每个测试文件均包含多组测试数据。第一行输入一个整数
代表数据组数,每组测试数据描述如下:
第一行输入一个整数
代表棍子的种类。
此后
行,第
行输入两个整数
代表第
种棍子的长度和数量。
除此之外,保证单个测试文件的
之和不超过
。
在一行上输出一个实数,代表组成的最大等腰三角形的面积。如果无法组成等腰三角形,则直接输出
。
由于实数的计算存在误差,当误差的量级不超过
时,您的答案都将被接受。具体来说,设您的答案为
,标准答案为
,当且仅当
时,您的答案将被接受。
2 3 3 3 2 1 3 1 2 1 2 12 1
3.89711431702997391060 -1
对于第一组测试数据,可以构造
为底、
为腰的三角形,面积
;也可以构造
为底、
为腰的三角形,面积
。显然,后者更大。
本题数据量较大,我们建议您使用较快的读入方式。
public static void main(String[] args) { Scanner in = new Scanner(System.in); int total = in.nextInt(); BigDecimal[] result = new BigDecimal[total]; for (int i = 0; i < total; i++) { int typeCount = in.nextInt(); int[][] lenAndNum = new int[typeCount][2]; for (int j = 0; j < typeCount; j++) { lenAndNum[j][0] = in.nextInt(); lenAndNum[j][1] = in.nextInt(); } result[i] = getResult(lenAndNum); } for (BigDecimal d : result) { System.out.println(d); } } public static BigDecimal getResult(int[][] lenAndNum) { Map<BigDecimal, Integer> map = new LinkedHashMap<>(); for (int i = 0; i < lenAndNum.length; i++) { BigDecimal len = BigDecimal.valueOf(lenAndNum[i][0]); int num = lenAndNum[i][1]; if (map.containsKey(len)) { map.put(len, map.get(len) + num); } else { map.put(len, num); } } map = map.entrySet().stream().sorted(Collections.reverseOrder( Map.Entry.comparingByKey())).collect( Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (l1, l2)->l1, LinkedHashMap::new)); List<BigDecimal> keyList = new LinkedList<>(); List<Integer> valueList = new LinkedList<>(); for (Map.Entry<BigDecimal, Integer> item : map.entrySet()) { keyList.add(item.getKey()); valueList.add(item.getValue()); } for (int i = 0; i < valueList.size(); i++) { Integer num = valueList.get(i); if (num >= 2) { for (int j = 0; j < Math.min(i + 1, valueList.size()); j++) { if (num > 2) { BigDecimal result = cal(keyList.get(i), keyList.get(j)); if (result.compareTo(BigDecimal.ZERO) > 0) { return result; } } if (num == 2 && i != j) { BigDecimal result = cal(keyList.get(i), keyList.get(j)); if (result.compareTo(BigDecimal.ZERO) > 0) { return result; } } } } } return BigDecimal.valueOf(-1); } public static BigDecimal cal(BigDecimal yao, BigDecimal di) { if (yao.add(yao).compareTo(di) < 0) { return new BigDecimal(-1); } BigDecimal halfDi = di.divide(BigDecimal.valueOf(2), 20, RoundingMode.HALF_UP); BigDecimal sqrtValue = yao.multiply(yao).subtract(halfDi.multiply( halfDi)); BigDecimal gao = sqrt(sqrtValue, 20); return di.multiply(gao).divide(BigDecimal.valueOf(2), 20, RoundingMode.HALF_UP); } public static BigDecimal sqrt(BigDecimal num, int precision) { // 负数不能开平方 if (num.compareTo(BigDecimal.ZERO) < 0) { throw new ArithmeticException("不能对负数开平方"); } MathContext context = new MathContext(precision, RoundingMode.HALF_UP); BigDecimal guess = num.divide(BigDecimal.valueOf(2), context); BigDecimal tolerance = BigDecimal.ONE.scaleByPowerOfTen(-precision); while (true) { BigDecimal nextGuess = guess.add(num.divide(guess, context)).divide(BigDecimal.valueOf(2), context); if (nextGuess.subtract(guess).abs().compareTo(tolerance) <= 0) { return nextGuess; } guess = nextGuess; } }