goj 三角形的周长

Problem Description:

有n根棍子,棍子i的长度为ai,想要从中选出3根棍子组成周长尽可能长的三角形。请输出最大的周长,若无法组成三角形则输出0。

Input:

输入包含多组测试,每组测试第一行输入一个整数n(3≤n≤10^5);第二行输入n个整数ai(1≤ai≤10^6);

Output:

对于每组测试,输出一个数字,表示最大周长,如果无法组成三角形,则输出0。

Sample Input:

5
2 3 4 5 10
4
5 4 20 10

Sample Output:

12
0
解题思路:这是《挑战程序设计竞赛(第二版)》里的一道题,书中说了一种解法O(n³),另外,还特意说明另有一种O(nlogn)的解法,留给读者思考。但对于此题来讲,由于给出n的范围最大值是10^5,所以不能用O(n³),而应该用O(nlogn)的解法。
我们知道组成三角形的充要条件是:最长的边小于其余两边之和;不难想到,可以三重循环枚举所有的选择方案,再判断能否组成三角形,最后找出最大的周长即可。不过此算法时间复杂度太大,会超时!
另一种方法是先把棍子进行排序,然后只比较相邻的三个棍子,最后选择最大的周长。这样只需一次循环即可。为什么这样就可行?理由:假如棍子已经升序排序了,有a<b<c<d,如果有a+b>c且a+b>d,程序中并没有比较a+b和d,那么是否会漏掉这种情况导致错误呢,不会的,因为如果a+b>d的话,那么b+c也一定大于d,而a+b又小于b+c,所以a+b和d后面的数的比较是多余的,而且若这两种情况同时成立,我们也只能取后一种的情况,因为要得到最长的周长!!!这样就只需比较相邻的三个棍子即可。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[1000005],n;
 4 int main(){
 5     while(cin>>n){
 6         for(int i=0;i<n;++i)
 7             cin>>a[i];
 8         sort(a,a+n);//默认升序排序
 9         int ans=0;
10         for(int i=0;i<n-2;++i){
11             int len=a[i]+a[i+1]+a[i+2];//三角形的周长
12             if(a[i]+a[i+1]>a[i+2])ans=max(ans,len);//证明出来的结论
13         }
14         cout<<ans<<endl;
15     }
16     return 0;
17 }

 

posted @ 2018-05-05 09:14  霜雪千年  阅读(758)  评论(0编辑  收藏  举报