每个测试文件均包含多组测试数据。第一行输入一个整数
代表数据组数,每组测试数据描述如下:
第一行输入一个整数
代表棍子的种类。
此后
行,第
行输入两个整数
代表第
种棍子的长度和数量。
除此之外,保证单个测试文件的
之和不超过
。
在一行上输出一个实数,代表组成的最大等腰三角形的面积。如果无法组成等腰三角形,则直接输出
。
由于实数的计算存在误差,当误差的量级不超过
时,您的答案都将被接受。具体来说,设您的答案为
,标准答案为
,当且仅当
时,您的答案将被接受。
2 3 3 3 2 1 3 1 2 1 2 12 1
3.89711431702997391060 -1
对于第一组测试数据,可以构造
为底、
为腰的三角形,面积
;也可以构造
为底、
为腰的三角形,面积
。显然,后者更大。
本题数据量较大,我们建议您使用较快的读入方式。
use std::collections::HashMap;
use std::io::*;
fn solve(group: HashMap<usize, usize>) {
let congruent_group: HashMap<usize, usize> = group
.iter()
.filter(|(_, &v)| v >= 2)
.map(|(k, v)| (*k, *v))
.collect();
if congruent_group.is_empty() {
println!("-1");
return;
}
let mut max_area = 0.0f64;
let mut found = false;
for base_side in group.iter() {
let (&length_b, _) = base_side;
for congruent_side in congruent_group.iter() {
let (&length_c, &count_c) = congruent_side;
if 2 * length_c <= length_b {
continue;
}
if length_b != length_c && count_c < 2 {
continue;
}
if length_b == length_c && count_c < 3 {
continue;
}
found = true;
let area = (length_b as f64)
* (length_c.pow(2) as f64 - length_b.pow(2) as f64 / 4.0).sqrt()
/ 2.0;
max_area = max_area.max(area);
}
}
if found {
println!("{}", max_area);
} else {
println!("-1");
}
}
fn main() {
let stdin = stdin();
let mut line = String::new();
stdin.read_line(&mut line).unwrap();
line.pop();
let t: usize = line.parse().unwrap();
for _ in 0..t {
line.clear();
stdin.read_line(&mut line).unwrap();
line.pop();
let n: usize = line.parse().unwrap();
let lines: Vec<(usize, usize)> = stdin
.lock()
.lines()
.take(n)
.map(|l| {
let l = l.unwrap();
let mut it = l.split_whitespace();
(
it.next().unwrap().parse().unwrap(),
it.next().unwrap().parse().unwrap(),
)
})
.collect();
let group = lines.iter().fold(HashMap::new(), |mut acc, &(a, b)| {
acc.entry(a).and_modify(|x| *x += b).or_insert(b);
acc
});
solve(group);
}
}