1. 由于题目不保证给出的木棍长度各不相同,所以处理输入时,长度相同的木棍,进行数量叠加。叠加时注意,如果数量超过了3,直接数量改写为3,因为我们只需组合一个三角形,再多没用,而且数量叠加起来还可能爆int。
  2. 然后题目要求是等腰三角形,因此先选一个最长的边 作为腰(数量至少有2 才有资格),这是因为,如果存在某个等腰三角形(腰长 < 我们的腰),把它替换成我们的腰(底不变),显然面积更大。
  3. 最后再遍历一遍,选底边,然后更新答案,成为底边的要求是:底边 < 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");
    }
}