題目大意:從 $n$ 根木棒裡選出六根拼成兩個合法的三角形,使這兩個三角形的周長和最大。
考慮貪心,證明在後面。
首先我們要知道一個三角形基本定理:較短兩邊長度之和大於最長邊。
那我們就根據這個定理先去尋找最大三角形的最長邊。
先排序,然後迴圈列舉,對於每個 $a_i$,可以尋找到的最大的其餘兩邊為 $a_{i-1}$ 與 $a_{i-2}$,如果該組不合法,那麼其餘組也不合法,否則我們就儲存當前的 $i$,把最大的兩組加起來輸出即可。
但是這題還有個比較坑的地方,兩組合法三角形的邊可能產生衝突,解決方法也很簡單:從最大三角形的最長邊往下找六條邊,只要裡面還有一種組合合法那就是最優解,否則無解。
證明:
設可以選的最大邊為為 $s_m$,那麼對於一組可選邊 $s_i$,$s_j$,會有以下幾種情況:
- $s_i$ 與 $s_j$ 不衝突,那麼 $s_i$ 與 $s_m$ 肯定也不衝突,所以選 $s_i$ 和 $s_m$。
- $s_i$ 與 $s_j$ 衝突,但 $s_j$ 與 $s_m$ 不衝突,那麼選 $s_j$ 與 $s_m$ 最優。
- $s_i$ 與 $s_j$ 衝突,但 $s_i$ 與 $s_m$ 不衝突,那麼選 $s_i$ 與 $s_m$ 最優。
- $s_i$ 與 $s_j$ 衝突,並且它們與 $s_m$ 都有衝突,那麼選哪組都對答案無影響。
證畢。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a,s,d[100005],f[100005];
ll ans,sum,cnt,maxn;
int main() {
scanf("%lld",&a);
for(int i=1;i<=a;i++){
scanf("%lld",&d[i]);
}
sort(d+1,d+a+1);
for(int i=3;i<=a;i++){
if(d[i]<d[i-1]+d[i-2]){
f[++cnt]=i;
}
}
for(int i=1;i<=cnt;i++){
if(f[cnt]-f[i]>=3){
maxn=i;
}
}
if(maxn!=0){
ans=d[f[cnt]]+d[f[cnt]-1]+d[f[cnt]-2]+d[f[maxn]]+d[f[maxn]-1]+d[f[maxn]-2];
}
if(f[cnt]>=6){
ll num1=d[f[cnt]-5],num2=d[f[cnt]-4],num3=d[f[cnt]-3],num4=d[f[cnt]-2],num5=d[f[cnt]-1],num6=d[f[cnt]];
sum=num1+num2+num3+num4+num5+num6;
if(num1+num2>num3&&num4+num5>num6){
ans=sum;
}
if(num1+num2>num4&&num3+num5>num6){
ans=sum;
}
if(num1+num2>num5&&num3+num4>num6){
ans=sum;
}
if(num1+num2>num6&&num3+num4>num5){
ans=sum;
}
if(num1+num3>num4&&num2+num5>num6){
ans=sum;
}
if(num1+num3>num5&&num2+num4>num6){
ans=sum;
}
if(num1+num3>num6&&num2+num4>num5){
ans=sum;
}
if(num1+num4>num5&&num2+num3>num6){
ans=sum;
}
if(num1+num4>num6&&num2+num3>num5){
ans=sum;
}
if(num1+num5>num6&&num2+num3>num4){
ans=sum;
}
}
printf("%lld\n",ans);
return 0;
}