【校内模拟】三角形
三角形
时限:\(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\%\)的数据,\(1\leq n\leq 10^3\)
对于前\(100\%\)的数据,\(1\leq T\leq 10,1\leq n\leq 10^5,a_i \leq 10^{9}\)
对于另外\(0\%\)的数据,\(1\leq 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\n",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\n",ans);
break;
}
if(!flag) puts("No Answer!");
}
return 0;
}
然而由于数据是随机的
直接找前三个最大数就可以过
不管不管不是我的锅嘤嘤嘤