输入
n = 5
a = {2,3,4,5,10}
输出
12(选择3、4、5时)
输入
n = 4
a = {4,5,10,20}
输出
0(无论怎么选都无法组成三角形)
思路:
《挑战程序设计竞赛》热身题,书上只给了O(n³)暴力解法,另有O(nlogn)的高效解法。
方案一:可否组成三角形的充要条件是:最长边>另两边之和,因为此题规模也不大n=100,考虑三重循环也行,枚举出所有的选择。
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int a[N];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int len,mx,rest,ans=0;
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
for(int k=j+1;k<n;k++)
{
len=a[i]+a[j]+a[k];//周长
mx=max(a[i],max(a[j],a[k]));
rest=len-mx;//另两边之和
if(rest>mx)
ans=len;
}
printf("%d\n",ans);
return 0;
}
方案二:能让我想到的是贪心,排个序,贪最大边长,从后往前考虑,先确定最长一条边,往前找另外两条小边,但好像又陷入了随机选取方案,后来发现考虑两条小边的相对位置是多余的,若随机分布了a<b<c<d<e<f; 当选了大边f,最有可能的两条小边就是相邻的d和e,因为如果选了a和b,或a和c等等 可以组成三角形的话,a+b < d+e,那么d和e一定更加是最优解,所以从后往前选取相邻的三条即可,找到即是最大的。排序复杂度用了O(nlogn)。
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int a[N];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
int ans=0,len;
for(int i=n-1;i>2;i--)
{
int len=a[i-1]+a[i-2]+a[i];
if(a[i-1]+a[i-2]>a[i])
{
ans=len;
break;
}
}
printf("%d\n",ans);
return 0;
}