题目简单描述:有n个长度一定的木棍,问这些木棍组成的三角形的最大面积为多少?
题目链接:三角形牧场 - 洛谷
我来分享一下搜索的解法,虽然正解是dp(bushi)。首先暴力搜索的思路就是我们枚举每一条木棍看把他加到三条边的那一条边中,但是这样显然会tle的。所以我们先考虑第一个优化就是进行排序,排序后的序列我们保证他是一个有序序列,在序列有序的情况下我们是从小到大排序,所以我们在进行了多次递归之后我们在回溯的时候是优先对于较大的边进行调整所以可以较为优先的搜到答案,可是我们发现这样做只有56分,那么我们继续考虑优化三角形成立的条件为两边之和大于第三边,并且我们可以知道这个三角形的周长为定值所以我们根据均值不等式不能得出在三边的边长相近的时候会出现最大的答案,所以我们就按照尽量使他们的三边相等为第一关键字来安排搜索。
显然我们是不可能搜完的但是我们可以在1s之内把答案搜到就成功了。
code:
#include <bits/stdc++.h>
using namespace std;
int qaq[100010];
int maxx = -1;
int a;
int t1,t2;
int calc(int l1,int l2,int l3) { //海伦公式计算
double faq = (double)(l1 + l2 + l3) / 2;
double ans = sqrt(faq * (faq - l1) * (faq - l2) * (faq - l3)) * 100;
return (int)ans;
}
void dfs(int num,int l1,int l2,int l3) { //搜索部分
t2 = clock();
if(t2 - t1 > 900000) { //计算程序运行的时间在1s之内输出答案。
cout<<maxx;
exit(0);
}
if(num == a + 1) { //完成了一次搜索对答案进行统计。
if(l1 + l2 <= l3)
return;
if(l1 + l3 <= l2)
return;
if(l3 + l2 <= l1)
return;
maxx = max(calc(l1,l2,l3),maxx);
}
else {
if(l1 <= l2 && l1 <= l3) { //我们开始贪心 尽量使他们的三条边相近。
dfs(num + 1,l1 + qaq[num],l2,l3);
if(l2 <= l3) { //当前l1为最小的我们向l1上加边。再判断l2和l3的大小。
dfs(num + 1,l1,l2 + qaq[num],l3);
dfs(num + 1,l1,l2,l3 + qaq[num]);
}
else {
dfs(num + 1,l1,l2,l3 + qaq[num]);
dfs(num + 1,l1,l2 + qaq[num],l3);
}
}
if(l2 <= l1 && l2 <= l3) { //同理如上 当前l2是最小的。优先搜索l2
dfs(num + 1,l1,l2 + qaq[num],l3);
if(l1 <= l3) {
dfs(num + 1,l1 + qaq[num],l2,l3);
dfs(num + 1,l1,l2,l3 + qaq[num]);
}
else {
dfs(num + 1,l1,l2,l3 + qaq[num]);
dfs(num + 1,l1 + qaq[num],l2,l3);
}
}
if(l3 <= l2 && l3 <= l1) { //同理
dfs(num + 1,l1,l2,l3 + qaq[num]);
if(l1 <= l2) {
dfs(num + 1,l1 + qaq[num],l2,l3);
dfs(num + 1,l1,l2 + qaq[num],l3);
}
else {
dfs(num + 1,l1,l2 + qaq[num],l3);
dfs(num + 1,l1 + qaq[num],l2,l3);
}
}
}
}
int main() {
t1 = clock();
cin>>a;
for(int i = 1;i <= a;i ++) {
cin>>qaq[i];
}
sort(qaq + 1,qaq + 1 + a);
dfs(1,0,0,0);
cout<<maxx;
return 0;
}