1 条题解

  • 0
    @ 2026-4-27 16:52:05

    Description

    给定 nn 个直角三角形,第 ii 个三角形的斜边长度为 rir_i
    设该三角形的一条直角边为 hih_i(称为高度),另一条直角边为 wiw_i,则有:

    hi2+wi2=ri2h_i^2 + w_i^2 = r_i^2

    该三角形的面积为:

    $$A_i = \frac12 h_i w_i = \frac12 h_i \sqrt{r_i^2 - h_i^2}$$

    在满足约束条件

    i=1nhiS,hi0\sum_{i=1}^n h_i \le S,\quad h_i \ge 0

    的前提下,求所有三角形面积之和的最大值。

    Analysis

    Step 1

    对固定的斜边长度 rr,定义面积函数:

    fr(h)=12hr2h2f_r(h) = \frac12 h\sqrt{r^2 - h^2}

    h[0,r2]h \in \left[0, \frac{r}{\sqrt2}\right] 时,有:

    • fr(h)f_r(h) 单调递增;
    • fr(h)f_r(h) 为严格凹函数;
    • 最大值在 h=r2h=\frac{r}{\sqrt2} 处取得;
    • 最大面积为 r24\frac{r^2}{4}

    其导数为:

    fr(h)=r22h22r2h2f_r'(h) = \frac{r^2 - 2h^2}{2\sqrt{r^2 - h^2}}

    在区间 [0,r2]\left[0, \frac{r}{\sqrt2}\right] 上,
    fr(h)f_r'(h)r2\frac r2 单调下降到 00


    Step 2

    若满足:

    Si=1nri2S \ge \sum_{i=1}^n \frac{r_i}{\sqrt2}

    则可以让每个三角形都取到最大面积,此时剩余高度不会再产生贡献。

    答案直接为:

    i=1nri24\sum_{i=1}^n \frac{r_i^2}{4}

    后续只需考虑 SS 不足的情况。

    SS 不足以让所有三角形达到最大面积时, 最优解必然满足高度约束是紧的:

    i=1nhi=S\sum_{i=1}^n h_i = S

    构造拉格朗日函数:

    $$L = \sum_{i=1}^n f_{r_i}(h_i) - \lambda\left(\sum_{i=1}^n h_i - S\right)$$

    对每个 hih_i 求偏导并令其为零,可得最优性条件:

    fri(hi)=λf_{r_i}'(h_i) = \lambda

    这意味着: 在最优解中,每个三角形的“单位高度带来的边际面积收益”是相同的。

    Step 3

    由条件:

    r22h22r2h2=λ\frac{r^2 - 2h^2}{2\sqrt{r^2 - h^2}} = \lambda

    设:

    t=r2h2t = \sqrt{r^2 - h^2}

    可化为一元二次方程:

    2t2+2λtr2=02t^2 + 2\lambda t - r^2 = 0

    取正根:

    t=λ+λ2+2r22t = \frac{\lambda + \sqrt{\lambda^2 + 2r^2}}{2}

    于是:

    h=r2t2h = \sqrt{r^2 - t^2}

    λr2\lambda \ge \frac r2 时,最优解为 h=0h=0


    Step 4

    对于固定的 rrh(λ)h(\lambda)λ\lambda 单调递减, 因此:

    H(λ)=i=1nhi(λ)H(\lambda) = \sum_{i=1}^n h_i(\lambda)

    也是单调递减函数。

    可以在区间:

    [0, max(ri)/2][0,\ \max(r_i)/2]

    内对 λ\lambda 进行二分, 寻找满足 H(λ)=SH(\lambda)=S 的值。

    可以证明二分次数不大于 100100 次。

    确定 λ\lambda 后:

    1. 对每个三角形计算对应的最优高度 hih_i
    2. 累加面积:
    i=1n12hiri2hi2\sum_{i=1}^n \frac12 h_i \sqrt{r_i^2 - h_i^2}

    即为所求答案。

    Code

    #include <iostream>
    #include <iomanip>
    #include <cmath>
    #include <algorithm>
    
    using ll = long long int;
    using ld = long double;
    static constexpr int MAXN = 1e5 + 10;
    
    int n;
    
    ld max_r, S, r[MAXN];
    
    inline ld best_h(ld R, ld lambda) {
    	if (lambda >= R * 0.5) return 0.0;
    	
    	ld disc = lambda * lambda + 2.0 * R * R;
    	ld t = (lambda + std::sqrt(disc)) * 0.5;
    	
    	ld x = R * R - t * t;
    	if (x <= 0.0L) return 0.0;
    	ld h = std::sqrt(x);
    	
    	ld cap = R / std::sqrt(2.0);
    	if (h > cap) h = cap;
    	return h;
    }
    
    inline ld area(ld R, ld h) {
    	ld t2 = R * R - h * h;
    	if (t2 <= 0.0) return 0.0;
    	return 0.5 * h * std::sqrt(t2);
    }
    
    int main() {
    	std::ios::sync_with_stdio(false);
    	std::cin.tie(nullptr);
    	
    	std::cin >> n >> S;
    	
    	for (int i = 1; i <= n; ++i) {
    		std::cin >> r[i];
    		max_r = std::max(max_r, r[i]);
    	}
    	
    	ld sum_cap = 0.0;
    	ld maxS = 0.0;
    	
    	for (int i = 1; i <= n; ++i) {
    		sum_cap += r[i] / std::sqrt(2.0L);
    		maxS += (r[i] * r[i]) * 0.25L;
    	}
    	
    	std::cout << std::fixed << std::setprecision(10);
    	
    	if (S >= sum_cap) {
    		std::cout << maxS;
    		return 0;
    	}
    	
    	ld ql = 0.0, qr = max_r * 0.5;
    	for (int it = 1; it <= 120; ++it) {
    		ld mid = (ql + qr) * 0.5;
    		
    		ld totH = 0.0;
    		for (int i = 1; i <= n; ++i) totH += best_h(r[i], mid);
    		
    		if (totH > S) ql = mid;
    		else qr = mid;
    	}
    	
    	ld lambda = qr;
    	ld ans = 0.0L;
    	for (int i = 1; i <= n; ++i) {
    		ld h = best_h(r[i], lambda);
    		ans += area(r[i], h);
    	}
    	
    	std::cout << ans;
    	
    	
    	return 0;
    }
    
    • 1

    信息

    ID
    7466
    时间
    1000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者