三角形
时限:(100ms) 空间:(512MB)
【题目背景】
无
【题目描述】
有(n)个木棍,现在知道了每个木棍的长度,要从中挑出三个木棍组成一个三角形,
如何挑选木棍,使得组成的三角形的面积最大
由于出题人不会做
由于上面的要求过于毒瘤,
良心的出题人将题面改为了求一个方案使得三角形的周长最大
输出这个三角形的三边长和面积
【输入输出格式】
输入格式
第一行一个整数(T),表示数据组数
对于每组数据
第一行一个整数(n),表示木棍的个数
第二行(n)个整数,表示这(n)个木棍的长度
输出格式
对于T组数据
若不能构成三角形,输出"(!No~ Answer!)"
否则
第一行从小到大输出三个整数(a,b,c),表示周长最大的三角形的三边长
第二行输出一个数,表示三角形的面积,只需要精确到整数
【输入输出样例】
输入样例
输入样例#1:
1
5
1 2 3 4 5
输入样例#2:
1
5
1 1 2 3 5
输出样例
输出样例#1:
3 4 5
6
输出样例#2:
No Answer!
【数据范围】
对于前(50\%)的数据,(1leq nleq 10^3)
对于前(100\%)的数据,(1leq Tleq 10,1leq nleq 10^5,a_i leq 10^{9})
对于另外(0\%)的数据,(1leq T leq 10^{10^{10^{10}}}!, 1 leq n leq 10^{10^{10^{10^{10^{10}}}}}),(a_i)在复数系范围内
海伦公式:(S=sqrt {p(p-a)(p-b)(p-c)})
(mathcal{solution})
显然,我们可以贪心地不断找最长的三条边,如果可以构成三角形,就输出答案
(sort)一遍复杂度是(O(T*nlogn))的,期望得分(50)分
然而我们发现实际上如果(n>50),那么一定会存在三角形
因为(a_i)的范围比较小,如果(50)个边仍无法构成三角形的话
我们考虑边的大小递增
第(1、2)个边长最小为(1),那么第(3)个边最小为(1+1=2),
第(4)个边最小为(1+2=3),第(5)个边最小为(2+3=5)……
显然第(50)条边为(fib_{50}),它是远大于(a_i)的范围的
所以当(n geq 50)时,
所以可以用(STL)的(nth\_element)将前(50)大的搞到一块儿,
将这(50)个(sort)一边贪心地取即可
求面积直接套公式即可,记得要用(double)
(mathcal{std})
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 10000010
int T,n,a[N];
const int ch_top=5e8+3;
char ch[ch_top],*now_r=ch-1;
inline int read(){
while(*++now_r<'0');
register int x=*now_r-'0';
while(*++now_r>='0')x=(x<<3)+(x<<1)+*now_r-'0';
return x;
}
int main()
{
fread(ch,1,ch_top,stdin);
T=read();
while(T--){
n=read();
for(int i=1;i<=n;++i)
a[i]=read();
if(n>50){
nth_element(a+1,a+1+n-50,a+1+n);
sort(a+1+n-50,a+1+n);
}
else sort(a+1,a+1+n);
bool flag=0;
long double x,y,z,p,ans;
for(int i=n-2;i>=1;--i)
if(a[i]+a[i+1]>a[i+2]){
flag=1;
printf("%d %d %d
",a[i],a[i+1],a[i+2]);
x=a[i],y=a[i+1],z=a[i+2];
p=(x+y+z)/2.0;
ans=sqrtl(p*(p-a[i])*(p-a[i+1])*(p-a[i+2]));
printf("%.0Lf
",ans);
break;
}
if(!flag) puts("No Answer!");
}
return 0;
}
然而由于数据是随机的
直接找前三个最大数就可以过
不管不管不是我的锅嘤嘤嘤