1. 程式人生 > >浙江中醫藥大學大學生程式設計競賽problemC Wpremig的三角形(二分計算幾何)

浙江中醫藥大學大學生程式設計競賽problemC Wpremig的三角形(二分計算幾何)

在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述
這題就太有說法了…像我這種萌新看完之後完全沒思路,我能回爐從造嗎
這是一道好題,看題解全程跪著看完的,防止忘了還是寫個…
如果想面積最大,那麼每兩個三角形相交的位置和每邊緣的三角形與邊界相交的位置一樣高,設這個高度為mid,mid下面是一個矩形,答案就是高度的三角形面積和加上這個矩形面積
對每個三角形,因為想高度最大所以最短邊貼著底邊的,有三角形面積公式
p=(a+b+c)/2;
area=sqrt(p
(p-a)(p-b)(p-c))
*
這個三角形的最大高度就是
h=area*2/h;
寫一個求底邊之和的函式f()
mid二分求,對於已mid為底邊的三角形,底邊之和f(mid)=l
求出mid後把每個部分的面積加起來就是答案了
三角形面積。。。?
底乘高除二啊(高中學的全忘了是這樣沒錯了)!
在這裡插入圖片描述

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn=100010;
const double eps=1e-6;
double a[maxn],b[maxn],c[maxn],h[maxn],area[maxn];
int n;double len;int t;
double f(double k){
    double ret=0;
    for(int i=1;i<=n;i++){
        if(k<h[i]){
            ret+=a[i]*(1.0-k/h[i]);
        }
    }return ret;
}
int main(){
    int i;
    scanf("%d",&t);
    while(t--){
        scanf("%d%lf",&n,&len);
        for(i=1;i<=n;i++){
            scanf("%lf%lf%lf",&a[i],&b[i],&c[i]);
            double p=(a[i]+b[i]+c[i])/2;
            area[i]=sqrt(p*(p-a[i])*(p-b[i])*(p-c[i]));
            h[i]=area[i]*2.0/a[i];
            //cout<<h[i]<<endl;
        }
        double mid,l=0,r=100000;
        while(fabs(r-l)>eps){
            mid=(l+r)/2.0;
            if(f(mid)<=len){
                r=mid;
            }else{
                l=mid;
            }
        }double ans=0;
        for(i=1;i<=n;i++){
            if(mid<h[i]){
                ans+=a[i]*(1.0-mid/h[i])*(h[i]-mid)/2.0;
            }
        }
        ans+=mid*len;
        printf("%.3f\n",ans);
    }
}