题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5135
题意:
给你n个长度的线段,让你组成三角形,最后输出所有能组成的三角形的面积和的最大值,每条线段只能使用一次。
解:
首先我们得知道什么情况下,我们所构造的三角形面积最大。
现在我们拥有长短不一的线段。
那么,问题转化成是长度差不多的线段组成的三角形面积总和较大,还是最长的线段组成的三角形和最短的线段组成的三角形总面积大。
那么我们可以来看下样例中三角形面积:
3 3 4 和 4 5 5的面积大于3 4 5和3 4 5的面积和。
可以看出将尽可能大的边组成的三角形面积更大。
所以直接对线段排序,从大到小遍历一边就行。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
int s[25];
double area(int a,int b,int c)
{
double aa=(double)a,bb=(double)b,cc=(double)c;
//cout<<aa<<" "<<bb<<" "<<cc<<" "<<endl;
double x=(aa*aa+cc*cc-bb*bb)/(2*cc);
//cout<<x<<endl;
//cout<<aa*aa-x*x<<endl;
double h=sqrt(fabs(aa*aa-x*x));
//cout<<h<<endl;
//cout<<"Area:"<<h*cc/2.0<<endl;;
return h*c/2.0;
}
bool judge(int a,int b,int c)
{
int mxx=max(a,max(b,c));
int sum;
if(a==mxx)sum=b+c;
else if(b==mxx)sum=a+c;
else sum=a+b;
if(mxx>=sum)return false;
else return true;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n==0)break;
for(int i=0;i<n;i++)
{
scanf("%d",&s[i]);
}
sort(s,s+n);
double sum=0.0;
for(int i=n-3;i>=0;i--)
{
if(!judge(s[i],s[i+1],s[i+2]))
{continue;}
else
{
double tmp=area(s[i],s[i+1],s[i+2]);
sum+=tmp;
i-=2;
}
}
printf("%.2lf\n",sum);
}
return 0;
}