プログラミングコンテストチャレンジブック 题解
题目大意:从 \(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;
}

浙公网安备 33010602011771号