- 由于题目不保证给出的木棍长度各不相同,所以处理输入时,长度相同的木棍,进行数量叠加。叠加时注意,如果数量超过了3,直接数量改写为3,因为我们只需组合一个三角形,再多没用,而且数量叠加起来还可能爆int。
- 然后题目要求是等腰三角形,因此先选一个最长的边 作为腰(数量至少有2 才有资格),这是因为,如果存在某个等腰三角形(腰长 < 我们的腰),把它替换成我们的腰(底不变),显然面积更大。
- 最后再遍历一遍,选底边,然后更新答案,成为底边的要求是:底边 < 2*腰长 且 数量 >= 1。
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <cmath>
using namespace std;
double calc_area(int a, int b, int c){
double p = (double(a) + double(b) + double(c))/2;
return sqrt(p*(p-a)*(p-b)*(p-c));
}
double solve(unordered_map<int,int>& rec){
//寻找最大值做腰(数量至少为2)
int max_y = 0;
for(auto [k, v] : rec){
if(v >= 2){
max_y = max(max_y, k);
}
}
if(max_y == 0){
return -1.0;
}
rec[max_y] -= 2;
//遍历找合适的底
double ans = -1.0;
for(auto [k, v] : rec){
if(v >= 1 and k < max_y+max_y){
ans = max(ans, calc_area(max_y, max_y, k));
}
}
return ans;
}
int main() {
int t;
cin >> t;
unordered_map<int,int> rec;
while(t--){
int n;
cin >> n;
rec.clear();
rec.reserve(n);
for(int i=0;i<n;i++){
int li , ai;
cin >> li >> ai;
ai = min(ai, 3);
rec[li] += ai;
}
//cout << solve(rec) << endl;
auto res = solve(rec);
if(res > 0.0)
printf("%.8lf\n", res);
else
printf("-1\n");
}
}